2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Remote Server
|
2003-10-29 11:53:47 +01:00
|
|
|
* MODULE: inet_server.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Internet remote server.
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-10-29 04:17:45 +01:00
|
|
|
*
|
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
|
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "DecOSF" port
|
2002-10-29 04:31:20 +01:00
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "SGI" port
|
2002-10-29 04:17:45 +01:00
|
|
|
*
|
2002-10-30 07:40:58 +01:00
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2002-10-31 06:06:02 +01:00
|
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
2004-12-23 04:03:13 +01:00
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2004-04-29 00:36:29 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include "../jrd/common.h"
|
2001-07-12 07:46:06 +02:00
|
|
|
#include "../jrd/isc_proto.h"
|
|
|
|
#include "../jrd/divorce.h"
|
2005-04-11 17:33:18 +02:00
|
|
|
#include "../jrd/jrd_proto.h"
|
2002-12-07 14:49:37 +01:00
|
|
|
#include "../common/config/config.h"
|
2002-10-31 06:06:02 +01:00
|
|
|
#if !(defined VMS)
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <sys/param.h>
|
|
|
|
#endif
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
2002-09-18 14:50:13 +02:00
|
|
|
#if TIME_WITH_SYS_TIME
|
|
|
|
# include <sys/time.h>
|
|
|
|
# include <time.h>
|
|
|
|
#else
|
|
|
|
# if HAVE_SYS_TIME_H
|
|
|
|
# include <sys/time.h>
|
|
|
|
# else
|
|
|
|
# include <time.h>
|
|
|
|
# endif
|
2001-07-12 07:46:06 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2002-09-18 14:50:13 +02:00
|
|
|
#if HAVE_SYS_WAIT_H
|
|
|
|
# include <sys/wait.h>
|
|
|
|
#endif
|
2001-07-12 07:46:06 +02:00
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef VMS
|
|
|
|
#include <descrip.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
2002-08-22 12:48:26 +02:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <unistd.h>
|
2002-08-22 12:48:26 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <errno.h>
|
2003-11-08 17:40:17 +01:00
|
|
|
#include "../jrd/ibase.h"
|
2003-02-14 03:23:18 +01:00
|
|
|
#include "../jrd/jrd_pwd.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "../remote/remote.h"
|
|
|
|
#include "../jrd/license.h"
|
|
|
|
#include "../jrd/thd.h"
|
|
|
|
#include "../jrd/file_params.h"
|
|
|
|
#include "../remote/inet_proto.h"
|
|
|
|
#include "../remote/serve_proto.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/sch_proto.h"
|
2004-05-18 00:30:09 +02:00
|
|
|
#include "../jrd/thread_proto.h"
|
2005-03-26 06:02:09 +01:00
|
|
|
#include "../common/utils_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef UNIX
|
|
|
|
#ifdef NETBSD
|
|
|
|
#include <signal.h>
|
|
|
|
#else
|
|
|
|
#include <sys/signal.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2005-08-29 17:00:15 +02:00
|
|
|
#if (defined SUPERSERVER && defined UNIX && defined SERVER_SHUTDOWN)
|
|
|
|
#include "../common/classes/semaphore.h"
|
|
|
|
#define SHUTDOWN_THREAD
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef SUPERSERVER
|
|
|
|
#ifndef WIN_NT
|
2004-05-17 12:22:34 +02:00
|
|
|
const char* TEMP_DIR = "/tmp";
|
2001-05-23 15:26:42 +02:00
|
|
|
#define CHANGE_DIR chdir
|
|
|
|
#endif
|
2004-05-17 12:22:34 +02:00
|
|
|
const char* INTERBASE_USER_NAME = "interbase";
|
|
|
|
const char* INTERBASE_USER_SHORT = "interbas";
|
|
|
|
const char* FIREBIRD_USER_NAME = "firebird";
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-08-10 03:22:12 +02:00
|
|
|
#ifdef VMS
|
2001-05-23 15:26:42 +02:00
|
|
|
static int assign(SCHAR *);
|
2005-04-18 05:24:34 +02:00
|
|
|
#else
|
|
|
|
static void set_signal(int, void (*)(int));
|
2003-08-10 03:22:12 +02:00
|
|
|
#endif
|
2003-09-08 22:23:46 +02:00
|
|
|
static void signal_handler(int);
|
2005-04-11 17:33:18 +02:00
|
|
|
|
|
|
|
#if (defined SUPERSERVER && defined UNIX )
|
2006-01-16 17:49:15 +01:00
|
|
|
//static void signal_sigpipe_handler(int);
|
2005-08-29 17:00:15 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SHUTDOWN_THREAD
|
2005-04-11 17:33:18 +02:00
|
|
|
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg);
|
|
|
|
static void signal_term(int);
|
2005-08-29 17:00:15 +02:00
|
|
|
static void shutdown_init();
|
|
|
|
static void shutdown_fini();
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static TEXT protocol[128];
|
|
|
|
static int INET_SERVER_start = 0;
|
|
|
|
static USHORT INET_SERVER_flag = 0;
|
|
|
|
|
2004-03-26 00:12:50 +01:00
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
int CLIB_ROUTINE server_main( int argc, char** argv)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m a i n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Run the server with apollo mailboxes.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-01-28 08:50:41 +01:00
|
|
|
rem_port* port;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
// 01 Sept 2003, Nickolay Samofatov
|
|
|
|
// In GCC version 3.1-3.3 we need to install special error handler
|
|
|
|
// in order to get meaningful terminate() error message on stderr.
|
|
|
|
// In GCC 3.4 or later this is the default.
|
2006-05-19 17:17:02 +02:00
|
|
|
//#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
|
|
|
|
// std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
|
|
|
|
//#endif
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef VMS
|
|
|
|
argc = VMS_parse(&argv, argc);
|
|
|
|
#endif
|
|
|
|
|
2003-11-07 09:06:35 +01:00
|
|
|
const TEXT* const* const end = argc + argv;
|
2001-05-23 15:26:42 +02:00
|
|
|
argv++;
|
2003-11-07 09:06:35 +01:00
|
|
|
bool debug = false, standalone = false;
|
|
|
|
INET_SERVER_flag = 0;
|
2004-12-23 04:03:13 +01:00
|
|
|
int channel = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
protocol[0] = 0;
|
2003-11-07 09:06:35 +01:00
|
|
|
bool multi_client = false, multi_threaded = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
|
|
|
INET_SERVER_flag |= SRVR_multi_client;
|
2003-11-07 09:06:35 +01:00
|
|
|
multi_client = multi_threaded = standalone = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
2004-12-23 04:03:13 +01:00
|
|
|
int clients = 0;
|
2003-11-07 09:06:35 +01:00
|
|
|
bool done = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (argv < end) {
|
2004-12-23 04:03:13 +01:00
|
|
|
TEXT c;
|
|
|
|
const TEXT* p = *argv++;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (*p++ == '-')
|
|
|
|
while (c = *p++) {
|
|
|
|
switch (UPPER(c)) {
|
|
|
|
case 'D':
|
|
|
|
INET_SERVER_flag |= SRVR_debug;
|
2003-11-07 09:06:35 +01:00
|
|
|
debug = standalone = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
#ifndef SUPERSERVER
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
INET_SERVER_flag |= SRVR_multi_client;
|
|
|
|
if (argv < end)
|
2006-04-19 05:05:09 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (clients = atoi(*argv))
|
|
|
|
argv++;
|
2006-04-19 05:05:09 +02:00
|
|
|
}
|
2003-11-07 09:06:35 +01:00
|
|
|
multi_client = standalone = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'S':
|
2003-11-07 09:06:35 +01:00
|
|
|
standalone = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'I':
|
2003-11-07 09:06:35 +01:00
|
|
|
standalone = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'T':
|
2003-11-07 09:06:35 +01:00
|
|
|
multi_threaded = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'U':
|
2003-11-07 09:06:35 +01:00
|
|
|
multi_threaded = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
#endif /* SUPERSERVER */
|
|
|
|
|
2002-07-29 17:37:59 +02:00
|
|
|
case 'E':
|
2001-05-23 15:26:42 +02:00
|
|
|
if (ISC_get_prefix(p) == -1)
|
2004-04-29 00:36:29 +02:00
|
|
|
printf("Invalid argument Ignored\n");
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2005-03-26 06:02:09 +01:00
|
|
|
argv++; /* do not skip next argument if this one
|
2001-05-23 15:26:42 +02:00
|
|
|
is invalid */
|
2003-11-07 09:06:35 +01:00
|
|
|
done = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'P':
|
2005-03-26 06:02:09 +01:00
|
|
|
fb_utils::snprintf(protocol, sizeof(protocol), "/%s", *argv++);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2002-07-29 17:37:59 +02:00
|
|
|
case 'H':
|
|
|
|
case '?':
|
2004-04-29 00:36:29 +02:00
|
|
|
printf("Firebird TCP/IP server options are:\n");
|
|
|
|
printf(" -d : debug on\n");
|
2002-07-29 17:37:59 +02:00
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
|
|
|
// These options only applicable to super server
|
2004-04-29 00:36:29 +02:00
|
|
|
printf(" -m : multiclient - on\n");
|
|
|
|
printf(" -s : standalone - true\n");
|
|
|
|
printf(" -i : standalone - false\n");
|
2002-07-29 17:37:59 +02:00
|
|
|
|
2004-04-29 00:36:29 +02:00
|
|
|
printf(" -t : multithread - true (non pc only)\n");
|
|
|
|
printf(" -u : multithread - false (pc only)\n");
|
|
|
|
printf(" -t : multithread (non pc only\n");
|
2002-07-29 17:37:59 +02:00
|
|
|
#endif
|
|
|
|
|
2004-04-29 00:36:29 +02:00
|
|
|
printf(" -p<protocol> : specify protocol\n");
|
|
|
|
printf(" -h|? : print this help\n");
|
|
|
|
printf("\n");
|
|
|
|
printf(" (The following -e options used to be -h options)\n");
|
|
|
|
printf(" -e<firebird_root_dir> : set firebird_root path\n");
|
|
|
|
printf(" -el<firebird_lock_dir> : set runtime firebird_lock dir\n");
|
|
|
|
printf(" -em<firebird_msg_dir> : set firebird_msg dir path\n");
|
|
|
|
printf(" -z : print version\n");
|
2002-07-29 17:37:59 +02:00
|
|
|
|
|
|
|
exit(FINI_OK);
|
2001-05-23 15:26:42 +02:00
|
|
|
case 'Z':
|
2004-04-29 00:36:29 +02:00
|
|
|
printf("Firebird TCP/IP server version %s\n",
|
2001-05-23 15:26:42 +02:00
|
|
|
GDS_VERSION);
|
|
|
|
exit(FINI_OK);
|
|
|
|
}
|
|
|
|
if (done)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if (defined SUPERSERVER && defined UNIX )
|
2004-09-29 12:11:54 +02:00
|
|
|
/* set_signal(SIGPIPE, signal_sigpipe_handler); */
|
|
|
|
set_signal(SIGPIPE, signal_handler);
|
2001-05-23 15:26:42 +02:00
|
|
|
set_signal(SIGUSR1, signal_handler);
|
|
|
|
set_signal(SIGUSR2, signal_handler);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Fork off a server, wait for it to die, then fork off another,
|
|
|
|
but give up after 100 tries */
|
|
|
|
|
2002-10-31 06:06:02 +01:00
|
|
|
#if !(defined SUPERSERVER || defined VMS)
|
2001-05-23 15:26:42 +02:00
|
|
|
if (multi_client && !debug) {
|
|
|
|
set_signal(SIGUSR1, signal_handler);
|
2004-12-23 04:03:13 +01:00
|
|
|
int child;
|
|
|
|
for (int n = 0; n < 100; n++) {
|
2001-05-23 15:26:42 +02:00
|
|
|
INET_SERVER_start = 0;
|
|
|
|
if (!(child = fork()))
|
|
|
|
break;
|
|
|
|
while (wait(0) != child)
|
|
|
|
if (INET_SERVER_start) {
|
|
|
|
n = 0; /* reset error counter on "real" signal */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
gds__log("INET_SERVER/main: gds_inet_server restarted");
|
|
|
|
}
|
2003-09-08 22:23:46 +02:00
|
|
|
set_signal(SIGUSR1, SIG_DFL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (standalone) {
|
|
|
|
if (multi_client) {
|
|
|
|
#ifdef SUPERSERVER
|
2002-07-29 17:37:59 +02:00
|
|
|
|
|
|
|
// Remove restriction on username, for DEV builds
|
|
|
|
// restrict only for production builds. MOD 21-July-2002
|
|
|
|
#ifndef DEV_BUILD
|
2001-05-23 15:26:42 +02:00
|
|
|
TEXT user_name[256]; /* holds the user name */
|
|
|
|
/* check user id */
|
|
|
|
ISC_get_user(user_name, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
if (strcmp(user_name, "root") &&
|
|
|
|
strcmp(user_name, FIREBIRD_USER_NAME) &&
|
|
|
|
strcmp(user_name, INTERBASE_USER_NAME) &&
|
2003-11-07 09:06:35 +01:00
|
|
|
strcmp(user_name, INTERBASE_USER_SHORT))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
/* invalid user -- bail out */
|
2004-04-29 00:36:29 +02:00
|
|
|
fprintf(stderr,
|
2001-05-23 15:26:42 +02:00
|
|
|
"%s: Invalid user (must be %s, %s, %s or root).\n",
|
2002-09-08 09:56:54 +02:00
|
|
|
"fbserver", FIREBIRD_USER_NAME,
|
2001-05-23 15:26:42 +02:00
|
|
|
INTERBASE_USER_NAME, INTERBASE_USER_SHORT);
|
|
|
|
exit(STARTUP_ERROR);
|
|
|
|
}
|
2002-07-29 17:37:59 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
#else
|
|
|
|
if (setreuid(0, 0) < 0)
|
2004-04-29 00:36:29 +02:00
|
|
|
printf("Inet_server: couldn't set uid to superuser.\n");
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
INET_set_clients(clients);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!debug) {
|
2004-12-23 04:03:13 +01:00
|
|
|
int mask = 0; // FD_ZERO(&mask);
|
2004-03-12 08:00:52 +01:00
|
|
|
mask |= 1 << 2; // FD_SET(2, &mask);
|
|
|
|
divorce_terminal(mask);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-11-07 09:06:35 +01:00
|
|
|
{ // scope block
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY status_vector;
|
2004-05-15 02:58:46 +02:00
|
|
|
THREAD_ENTER();
|
2001-05-23 15:26:42 +02:00
|
|
|
port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag,
|
|
|
|
0, 0);
|
2004-05-15 02:58:46 +02:00
|
|
|
THREAD_EXIT();
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!port) {
|
|
|
|
gds__print_status(status_vector);
|
|
|
|
exit(STARTUP_ERROR);
|
|
|
|
}
|
2003-11-07 09:06:35 +01:00
|
|
|
} // end scope block
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef VMS
|
|
|
|
channel = assign("SYS$INPUT");
|
|
|
|
#endif
|
2004-05-15 02:58:46 +02:00
|
|
|
THREAD_ENTER();
|
2001-05-23 15:26:42 +02:00
|
|
|
port = INET_server(channel);
|
2004-05-15 02:58:46 +02:00
|
|
|
THREAD_EXIT();
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!port) {
|
2004-04-29 00:36:29 +02:00
|
|
|
fprintf(stderr, "fbserver: Unable to start INET_server\n");
|
2001-05-23 15:26:42 +02:00
|
|
|
exit(STARTUP_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SUPERSERVER
|
|
|
|
|
|
|
|
/* before starting the superserver stuff change directory to tmp */
|
|
|
|
if (CHANGE_DIR(TEMP_DIR)) {
|
|
|
|
/* error on changing the directory */
|
2005-03-23 11:32:28 +01:00
|
|
|
gds__log("Could not change directory to %s due to errno %d",
|
2001-05-23 15:26:42 +02:00
|
|
|
TEMP_DIR, errno);
|
|
|
|
}
|
|
|
|
|
2005-03-26 06:02:09 +01:00
|
|
|
/* Server tries to attach to security2.fdb to make sure everything is OK
|
2001-05-23 15:26:42 +02:00
|
|
|
This code fixes bug# 8429 + all other bug of that kind - from
|
|
|
|
now on the server exits if it cannot attach to the database
|
|
|
|
(wrong or no license, not enough memory, etc.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
TEXT path[MAXPATHLEN];
|
2003-04-16 12:18:51 +02:00
|
|
|
ISC_STATUS_ARRAY status;
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_db_handle db_handle = 0L;
|
|
|
|
|
2004-11-07 15:44:59 +01:00
|
|
|
SecurityDatabase::getPath(path);
|
2004-11-08 08:08:06 +01:00
|
|
|
const char dpb[] = {isc_dpb_version1, isc_dpb_gsec_attach, 1, 1};
|
2004-11-07 15:44:59 +01:00
|
|
|
isc_attach_database(status, strlen(path), path, &db_handle, sizeof dpb, dpb);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (status[0] == 1 && status[1] > 0) {
|
2004-11-07 15:44:59 +01:00
|
|
|
gds__log_status(path, status);
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_print_status(status);
|
|
|
|
exit(STARTUP_ERROR);
|
|
|
|
}
|
|
|
|
isc_detach_database(status, &db_handle);
|
|
|
|
if (status[0] == 1 && status[1] > 0) {
|
2004-11-07 15:44:59 +01:00
|
|
|
gds__log_status(path, status);
|
2001-05-23 15:26:42 +02:00
|
|
|
isc_print_status(status);
|
|
|
|
exit(STARTUP_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-11 17:33:18 +02:00
|
|
|
#endif
|
|
|
|
|
2005-08-29 17:00:15 +02:00
|
|
|
#ifdef SHUTDOWN_THREAD
|
|
|
|
shutdown_init();
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (multi_threaded)
|
|
|
|
SRVR_multi_thread(port, INET_SERVER_flag);
|
|
|
|
else
|
|
|
|
SRVR_main(port, INET_SERVER_flag);
|
|
|
|
|
2005-08-29 17:00:15 +02:00
|
|
|
#ifdef SHUTDOWN_THREAD
|
|
|
|
shutdown_fini();
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
/* In Debug mode - this will report all server-side memory leaks
|
|
|
|
* due to remote access
|
|
|
|
*/
|
2002-09-22 22:41:55 +02:00
|
|
|
//gds_alloc_report(0, __FILE__, __LINE__);
|
|
|
|
char name[MAXPATHLEN];
|
|
|
|
gds__prefix(name, "memdebug.log");
|
2004-11-27 04:33:22 +01:00
|
|
|
FILE* file = fopen(name, "w+t");
|
2002-09-22 22:41:55 +02:00
|
|
|
if (file) {
|
2004-06-29 06:37:59 +02:00
|
|
|
fprintf(file, "Global memory pool allocated objects\n");
|
2002-09-22 22:41:55 +02:00
|
|
|
getDefaultMemoryPool()->print_contents(file);
|
|
|
|
fclose(file);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
exit(FINI_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
static int assign( SCHAR * string)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* a s s i g n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Assign a channel for communications.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SSHORT channel;
|
|
|
|
struct dsc$descriptor_s desc;
|
|
|
|
|
|
|
|
desc.dsc$b_dtype = DSC$K_DTYPE_T;
|
|
|
|
desc.dsc$b_class = DSC$K_CLASS_S;
|
|
|
|
desc.dsc$w_length = strlen(string);
|
|
|
|
desc.dsc$a_pointer = string;
|
|
|
|
|
2004-12-23 04:03:13 +01:00
|
|
|
int status = sys$assign(&desc, &channel, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return (status & 1) ? channel : 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-10-31 06:06:02 +01:00
|
|
|
#if !(defined VMS)
|
2003-09-08 22:23:46 +02:00
|
|
|
static void set_signal( int signal_number, void (*handler) (int))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s e t _ s i g n a l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Establish signal handler.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
struct sigaction vec, old_vec;
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
vec.sa_handler = handler;
|
|
|
|
sigemptyset(&vec.sa_mask);
|
2001-05-23 15:26:42 +02:00
|
|
|
vec.sa_flags = 0;
|
|
|
|
sigaction(signal_number, &vec, &old_vec);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
static void signal_handler(int)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s i g n a l _ h a n d l e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Dummy signal handler.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
++INET_SERVER_start;
|
|
|
|
}
|
|
|
|
|
2006-01-16 17:49:15 +01:00
|
|
|
#ifdef NOT_USED_OR_REPLACED
|
2001-05-23 15:26:42 +02:00
|
|
|
#if (defined SUPERSERVER && defined UNIX )
|
2003-09-08 22:23:46 +02:00
|
|
|
static void signal_sigpipe_handler(int)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/****************************************************
|
|
|
|
*
|
|
|
|
* s i g n a l _ s i g p i p e _ h a n d l e r
|
|
|
|
*
|
|
|
|
****************************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Dummy signal handler.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
++INET_SERVER_start;
|
|
|
|
gds__log
|
|
|
|
("Super Server/main: Bad client socket, send() resulted in SIGPIPE, caught by server\n client exited improperly or crashed ????");
|
|
|
|
}
|
2005-08-29 17:00:15 +02:00
|
|
|
#endif //SUPERSERVER && UNIX
|
2006-01-16 17:49:15 +01:00
|
|
|
#endif
|
2005-08-29 17:00:15 +02:00
|
|
|
|
|
|
|
#ifdef SHUTDOWN_THREAD
|
|
|
|
static Firebird::Semaphore shutSem;
|
|
|
|
static bool alreadyClosing = false;
|
2005-04-11 17:33:18 +02:00
|
|
|
|
|
|
|
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
|
|
|
{
|
|
|
|
/****************************************************
|
|
|
|
*
|
|
|
|
* s h u t d o w n _ t h r e a d
|
|
|
|
*
|
|
|
|
****************************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* In order to avoid blocking of the thread,
|
|
|
|
* which received SIGTERM, run in separate thread.
|
|
|
|
*
|
|
|
|
**************************************/
|
2005-11-27 21:53:09 +01:00
|
|
|
try {
|
|
|
|
shutSem.enter();
|
|
|
|
}
|
|
|
|
catch (Firebird::status_exception& e)
|
|
|
|
{
|
|
|
|
TEXT buffer[1024];
|
2006-05-20 05:31:05 +02:00
|
|
|
const ISC_STATUS* vector = e.value();
|
|
|
|
if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector)))
|
2005-11-27 21:53:09 +01:00
|
|
|
{
|
|
|
|
strcpy(buffer, "Unknown failure in semaphore::enter()");
|
|
|
|
}
|
|
|
|
gds__log(buffer, 0);
|
|
|
|
exit(0);
|
|
|
|
}
|
2005-08-29 17:00:15 +02:00
|
|
|
if (! alreadyClosing)
|
|
|
|
{
|
|
|
|
alreadyClosing = true;
|
|
|
|
JRD_shutdown_all(false);
|
2006-04-14 18:46:12 +02:00
|
|
|
SRVR_shutdown();
|
2005-08-29 17:00:15 +02:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
return 0; //make compilers happy
|
2005-04-11 17:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void signal_term(int)
|
|
|
|
{
|
|
|
|
/****************************************************
|
|
|
|
*
|
|
|
|
* s i g n a l _ t e r m
|
|
|
|
*
|
|
|
|
****************************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Handle ^C and kill.
|
|
|
|
*
|
|
|
|
**************************************/
|
2005-08-29 17:00:15 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
shutSem.release();
|
|
|
|
}
|
|
|
|
catch (Firebird::status_exception& e)
|
|
|
|
{
|
|
|
|
TEXT buffer[1024];
|
2006-05-20 05:31:05 +02:00
|
|
|
const ISC_STATUS* vector = e.value();
|
|
|
|
if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector)))
|
2005-08-29 17:00:15 +02:00
|
|
|
{
|
|
|
|
strcpy(buffer, "Unknown failure in semaphore::release()");
|
|
|
|
}
|
|
|
|
gds__log(buffer, 0);
|
|
|
|
exit(0);
|
|
|
|
}
|
2005-04-11 17:33:18 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-08-29 17:00:15 +02:00
|
|
|
static void shutdown_init()
|
|
|
|
{
|
|
|
|
gds__thread_start(shutdown_thread, 0, THREAD_medium, 0, 0);
|
|
|
|
// process signals 2 & 15 in order to exit gracefully
|
|
|
|
set_signal(SIGINT, signal_term);
|
|
|
|
set_signal(SIGTERM, signal_term);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-08-29 17:00:15 +02:00
|
|
|
static void shutdown_fini()
|
|
|
|
{
|
|
|
|
set_signal(SIGINT, SIG_IGN);
|
|
|
|
set_signal(SIGTERM, SIG_IGN);
|
|
|
|
alreadyClosing = true;
|
|
|
|
shutSem.release();
|
|
|
|
}
|
|
|
|
#endif //SHUTDOWN_THREAD
|