8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 00:03:02 +01:00

fixed AV related with SVC_TRMNTR in services

This commit is contained in:
alexpeshkoff 2006-07-27 14:24:09 +00:00
parent b2e0ecd141
commit 028ab3c597
6 changed files with 101 additions and 242 deletions

View File

@ -105,7 +105,7 @@ static void expand_filename(const TEXT*, TEXT*);
#ifndef SERVICE_THREAD
static int output_main(Jrd::Service*, const UCHAR*);
#endif
static int common_main(int, char**, Jrd::pfn_svc_output, Jrd::Service*);
static int common_main(int, const char**, Jrd::pfn_svc_output, Jrd::Service*);
static void alice_output(const SCHAR*, ...) ATTRIBUTE_FORMAT(1,2);
@ -133,7 +133,7 @@ static int output_svc(Jrd::Service* output_data, const UCHAR * output_buf)
THREAD_ENTRY_DECLARE ALICE_main(THREAD_ENTRY_PARAM arg)
{
Jrd::Service* service = (Jrd::Service*)arg;
const int exit_code = common_main(service->svc_argc, service->svc_argv,
const int exit_code = common_main(service->svc_argc, service->svc_argv.begin(),
SVC_output, service);
// Mark service thread as finished.
@ -155,7 +155,7 @@ THREAD_ENTRY_DECLARE ALICE_main(THREAD_ENTRY_PARAM arg)
// Call the 'real' main.
//
int CLIB_ROUTINE main(int argc, char* argv[])
int CLIB_ROUTINE main(int argc, const char** argv)
{
const int exit_code = common_main(argc, argv, output_main, NULL);
@ -182,8 +182,8 @@ static int output_main(Jrd::Service* output_data, const UCHAR* output_buf)
// Parse switches and do work
//
int common_main(int argc,
char* argv[],
int common_main(int argc,
const char* argv[],
Jrd::pfn_svc_output output_proc,
Jrd::Service* output_data)
{
@ -464,14 +464,14 @@ int common_main(int argc,
if (--argc <= 0) {
ALICE_error(13); // msg 13: user name required
}
tdgbl->ALICE_data.ua_user = reinterpret_cast<UCHAR*>(*argv++);
tdgbl->ALICE_data.ua_user = reinterpret_cast<const UCHAR*>(*argv++);
}
if (table->in_sw_value & sw_password) {
if (--argc <= 0) {
ALICE_error(14); // msg 14: password required
}
tdgbl->ALICE_data.ua_password = reinterpret_cast<UCHAR*>(*argv++);
tdgbl->ALICE_data.ua_password = reinterpret_cast<const UCHAR*>(*argv++);
}
if (table->in_sw_value & sw_disable) {

View File

@ -186,8 +186,9 @@ THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM arg)
*
**************************************/
Jrd::Service* service = (Jrd::Service*)arg;
const int exit_code = common_main(service->svc_argc, service->svc_argv,
SVC_output, service);
const int exit_code = common_main(service->svc_argc,
const_cast<char**>(service->svc_argv.begin()),
SVC_output, service);
// Mark service thread as finished.
// If service is detached, cleanup memory being used by service.

View File

@ -130,8 +130,9 @@ const TEXT SVC_TRMNTR = '\377';
namespace Jrd {
Service::Service(serv_entry *se, Firebird::MemoryPool& p) :
svc_parsed_sw(p),
svc_handle(0), svc_status(svc_status_array), svc_input(0), svc_output(0),
svc_stdout_head(0), svc_stdout_tail(0), svc_stdout(0), svc_argv(0), svc_argc(0),
svc_stdout_head(0), svc_stdout_tail(0), svc_stdout(0), svc_argv(p), svc_argc(0),
svc_service(se), svc_resp_buf(0), svc_resp_ptr(0), svc_resp_buf_len(0),
svc_resp_len(0), svc_flags(0), svc_user_flag(0), svc_spb_version(0), svc_do_shutdown(false),
svc_username(p), svc_enc_password(p), svc_switches(p), svc_perm_sw(p)
@ -163,10 +164,6 @@ namespace Jrd {
{
gds__free(svc_stdout);
}
if (svc_argv)
{
gds__free(svc_argv);
}
#endif //SERVICE_THREAD
if (svc_resp_buf)
@ -178,6 +175,66 @@ namespace Jrd {
CloseHandle((HANDLE) svc_handle);
#endif
}
void Service::parseSwitches()
{
svc_parsed_sw = svc_switches;
svc_parsed_sw.trim();
svc_argc = 2;
if (svc_parsed_sw.isEmpty())
{
svc_parsed_sw.c_str();
svc_argv.getBuffer(svc_argc + 1)[1] = 0;
return;
}
bool inStr = false;
for (size_t i = 0; i < svc_parsed_sw.length(); ++i)
{
switch (svc_parsed_sw[i])
{
case SVC_TRMNTR:
svc_parsed_sw.erase(i, 1);
if (inStr)
{
if (i < svc_parsed_sw.length() && svc_parsed_sw[i] != SVC_TRMNTR)
{
inStr = false;
--i;
}
}
else
{
inStr = true;
--i;
}
break;
case ' ':
if (!inStr)
{
++svc_argc;
svc_parsed_sw[i] = 0;
}
break;
}
}
const char** argv = svc_argv.getBuffer(svc_argc + 1);
argv++; // leave space for argv[0]
*argv++ = svc_parsed_sw.c_str();
for (const char *p = svc_parsed_sw.begin();
p < svc_parsed_sw.end(); ++p)
{
if (!*p)
{
*argv++ = p + 1;
}
}
*argv = 0;
}
} //namespace
using namespace Jrd;
@ -549,7 +606,6 @@ Service* SVC_attach(USHORT service_length,
service->svc_stdout_head = 1;
service->svc_stdout_tail = SVC_STDOUT_BUFFER_SIZE;
service->svc_stdout = NULL;
service->svc_argv = NULL;
#endif
service->svc_spb_version = options.spb_version;
service->svc_username = options.spb_user_name;
@ -1767,78 +1823,8 @@ void* SVC_start(Service* service, USHORT spb_length, const SCHAR* spb_data)
#else
/* Break up the command line into individual arguments. */
if (service->svc_switches.hasData())
{
USHORT argc;
TEXT* p;
for (argc = 2, p = service->svc_switches.begin(); *p;) {
if (*p == ' ') {
argc++;
while (*p == ' ')
p++;
}
else {
if (*p == SVC_TRMNTR) {
while (*p++ && *p != SVC_TRMNTR);
fb_assert(*p == SVC_TRMNTR);
}
p++;
}
}
service->svc_argc = argc;
TEXT** arg = (TEXT **) gds__alloc((SLONG) ((argc + 1) * sizeof(TEXT *)));
/*
* the service block can be reused hence free a memory from the
* previous usage if any.
*/
if (service->svc_argv)
gds__free(service->svc_argv);
service->svc_argv = arg;
/* FREE: at SVC_detach() - Possible memory leak if ERR_post() occurs */
if (!arg) /* NOMEM: */
ERR_post(isc_virmemexh, 0);
*arg++ = (TEXT *)(serv->serv_thd);
const TEXT* q = p = service->svc_switches.begin();
while (*q == ' ')
q++;
while (*q) {
*arg = p;
while (*p = *q++) {
if (*p == ' ')
break;
if (*p == SVC_TRMNTR) {
*arg = ++p; /* skip terminator */
while (*p = *q++)
/* If *q points to the last argument, then terminate the argument */
if ((*q == 0 || *q == ' ') && *p == SVC_TRMNTR) {
*p = '\0';
break;
}
else
p++;
}
if (*p == '\\' && *q == ' ') {
*p = ' ';
q++;
}
p++;
}
arg++;
if (!*p)
break;
*p++ = '\0';
while (*q == ' ')
q++;
}
*arg = NULL;
}
service->parseSwitches();
service->svc_argv[0] = (TEXT *)(serv->serv_thd);
/*
* the service block can be reused hence free a memory from the
@ -2191,48 +2177,11 @@ static void service_fork(ThreadEntryPoint* service_executable, Service* service)
**************************************/
TEXT* p;
USHORT argc = 2;
for (p = service->svc_switches.begin(); *p;)
if (*p++ == ' ')
argc++;
service->svc_argc = argc;
TEXT** arg = (TEXT **) gds__alloc((SLONG) ((argc + 1) * sizeof(TEXT *)));
service->svc_argv = arg;
/* FREE: at SVC_detach() - Possible memory leak if ERR_post() occurs */
if (!arg) /* NOMEM: */
ERR_post(isc_virmemexh, 0);
*arg++ = (TEXT *)(service_executable);
/* Break up the command line into individual arguments. */
const TEXT* q = p = service->svc_switches.begin();
while (*q == ' ')
q++;
while (*q) {
*arg++ = p;
while ((*p = *q++) && *p != ' ') {
if (*p == '\\' && *q == ' ') {
*p = ' ';
q++;
}
p++;
}
if (!*p)
break;
*p++ = 0;
while (*q == ' ')
q++;
}
*arg = NULL;
service->svc_stdout = (UCHAR*)gds__alloc((SLONG) SVC_STDOUT_BUFFER_SIZE + 1);
/* FREE: at SVC_detach() */
if (!service->svc_stdout) /* NOMEM: */
ERR_post(isc_virmemexh, 0);
service->parseSwitches();
USHORT argc = service->svc_argc;
service->svc_argv[0] = (TEXT *)(service_executable);
THREAD_EXIT();
gds__thread_start(service_executable,
@ -2403,104 +2352,10 @@ static void service_fork(TEXT* service_path, Service* service)
if (statistics(service_path, &stat_buf) == -1)
io_error("stat", errno, service_path, isc_io_access_err);
/* Make sure we have buffers that are large enough to hold the number
and size of the command line arguments. */
TEXT* p;
USHORT argc = 2;
for (p = service->svc_switches.begin(); *p;)
{
if (*p == ' ')
{
argc++;
while (*p == ' ')
p++;
}
else
{
if (*p == SVC_TRMNTR)
{
while (*p++ && *p != SVC_TRMNTR);
fb_assert (*p == SVC_TRMNTR);
}
p++;
}
}
// Hardcoded, ISC_STATUS_LEN, platform specific or what????
TEXT* argv_buf[20];
TEXT** argv;
if (argc > FB_NELEM(argv_buf))
argv = (TEXT **) gds__alloc((SLONG) (argc * sizeof(TEXT *)));
else
argv = argv_buf;
/* FREE: at procedure return */
if (!argv) /* NOMEM: */
ERR_post(isc_virmemexh, 0);
service->svc_argc = argc;
TEXT argv_data_buf[512];
TEXT* argv_data;
const USHORT len = service->svc_switches.length() + 1;
if (len > sizeof(argv_data_buf))
argv_data = (TEXT *) gds__alloc((SLONG) len);
else
argv_data = argv_data_buf;
/* FREE: at procedure return */
if (!argv_data) { /* NOMEM: */
if (argv != argv_buf)
gds__free(argv);
ERR_post(isc_virmemexh, 0);
}
/* Break up the command line into individual arguments. */
TEXT** arg = argv;
*arg++ = service_path;
p = argv_data;
const TEXT* q = service->svc_switches.c_str();
while (*q == ' ')
q++;
while (*q)
{
*arg = p;
while (*p = *q++)
{
if (*p == ' ')
break;
if (*p == SVC_TRMNTR)
{
*arg = ++p; /* skip terminator */
while (*p = *q++)
/* If *q points to the last argument, then terminate the argument */
if ((*q == 0 || *q == ' ') && *p == SVC_TRMNTR)
{
*p = '\0';
break;
}
else
p++;
}
if (*p == '\\' && *q == ' ')
{
*p = ' ';
q++;
}
p++;
}
arg++;
if (!*p)
break;
*p++ = '\0';
while (*q == ' ')
q++;
}
*arg = NULL;
service->parseSwitches();
const char **argv = &service->svc_argv[0];
*argv = service_path;
/* At last we can fork the sub-process. If the fork succeeds, repeat
it so that we don't have defunct processes hanging around. */
@ -2512,10 +2367,6 @@ static void service_fork(TEXT* service_path, Service* service)
switch (pid = vfork()) {
case -1:
THREAD_ENTER();
if (argv != argv_buf)
gds__free(argv);
if (argv_data != argv_data_buf)
gds__free(argv_data);
ERR_post(isc_sys_request, isc_arg_string, "vfork", SYS_ERR, errno, 0);
break;
@ -2540,7 +2391,7 @@ static void service_fork(TEXT* service_path, Service* service)
#ifdef DEV_BUILD
{
char buf[2 * MAXPATHLEN];
char** s = argv;
const char** s = argv;
strcpy (buf, "service_fork:");
while (*s != (char *)0)
@ -2552,7 +2403,7 @@ static void service_fork(TEXT* service_path, Service* service)
gds__log(buf);
}
#endif
execvp(argv[0], argv);
execvp(argv[0], const_cast<char* const*>(argv));
_exit(FINI_ERROR);
}
@ -2563,11 +2414,6 @@ static void service_fork(TEXT* service_path, Service* service)
THREAD_ENTER();
if (argv != argv_buf)
gds__free(argv);
if (argv_data != argv_data_buf)
gds__free(argv_data);
if (!(service->svc_input = fdopen(pair1[0], "r")) ||
!(service->svc_output = fdopen(pair2[1], "w")))
{
@ -3136,6 +2982,14 @@ static void get_action_svc_string(const Firebird::ClumpletReader& spb,
**************************************/
Firebird::string s;
spb.getString(s);
for (size_t i = 0; i < s.length(); ++i)
{
if (s[i] == SVC_TRMNTR)
{
s.insert(i, 1, SVC_TRMNTR);
++i;
}
}
switches += SVC_TRMNTR;
switches += s;
switches += SVC_TRMNTR;

View File

@ -35,6 +35,7 @@
#include "../jrd/jrd_blks.h"
#include "../include/fb_blk.h"
#include "../common/classes/array.h"
void SVC_STATUS_ARG(ISC_STATUS*& status, USHORT type, const void* value);
@ -102,6 +103,8 @@ class Service : public pool_alloc<type_svc>
{
private:
ISC_STATUS_ARRAY svc_status_array;
Firebird::string svc_parsed_sw; // Here point elements of svc_argv
public:
Service(serv_entry *se, Firebird::MemoryPool& p);
~Service();
@ -113,7 +116,7 @@ public:
ULONG svc_stdout_head;
ULONG svc_stdout_tail;
UCHAR* svc_stdout;
TEXT** svc_argv;
Firebird::HalfStaticArray<const char*, 20> svc_argv;
ULONG svc_argc;
event_t svc_start_event[1]; /* fired once service has started successfully */
serv_entry* svc_service;
@ -132,6 +135,7 @@ public:
// and/or passed using spb_command_line
void svc_started();
void parseSwitches(); // Create svc_argv, svc_argc and svc_parsed_sw
};
/* Bitmask values for the svc_flags variable */

View File

@ -69,7 +69,7 @@ const int MAXSTUFF = 1000; /* longest interactive command line */
class tsec *gdsec;
#endif
static int common_main(int, char**, Jrd::pfn_svc_output, Jrd::Service*);
static int common_main(int, const char**, Jrd::pfn_svc_output, Jrd::Service*);
static void util_output(const SCHAR*, ...);
static void data_print(void*, const internal_user_data*, bool);
@ -101,7 +101,7 @@ THREAD_ENTRY_DECLARE GSEC_main(THREAD_ENTRY_PARAM arg)
* Entrypoint for GSEC via the services manager
**********************************************/
Jrd::Service* service = (Jrd::Service*)arg;
const int exit_code = common_main(service->svc_argc, service->svc_argv,
const int exit_code = common_main(service->svc_argc, service->svc_argv.begin(),
SVC_output, service);
/* Mark service thread as finished. */
@ -113,7 +113,7 @@ THREAD_ENTRY_DECLARE GSEC_main(THREAD_ENTRY_PARAM arg)
#else
int CLIB_ROUTINE main( int argc, char* argv[])
int CLIB_ROUTINE main( int argc, const char* argv[])
{
/**************************************
*
@ -160,7 +160,7 @@ inline void envPick(TEXT* dest, size_t size, const TEXT* var)
#endif /* SERVICE_THREAD */
int common_main(int argc,
char* argv[],
const char* argv[],
Jrd::pfn_svc_output output_proc,
Jrd::Service* output_data)
{

View File

@ -337,7 +337,7 @@ int CLIB_ROUTINE main(int argc, char** argv)
/* Reinitialize static variables for multi-threading */
Jrd::Service* service = (Jrd::Service*)arg;
int argc = service->svc_argc;
char** argv = service->svc_argv;
const char** argv = service->svc_argv.begin();
#endif
ISC_STATUS* status_vector = NULL;