mariadb/server-tools/instance-manager/mysqlmanager.cc

230 lines
5.5 KiB
C++
Raw Normal View History

/* Copyright (C) 2003-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
2007-02-20 12:28:24 +03:00
#include <my_dir.h>
#include <my_sys.h>
#include <string.h>
2005-07-20 10:55:40 -05:00
#ifndef __WIN__
2005-02-05 14:04:49 +03:00
#include <pwd.h>
#include <grp.h>
2005-07-20 10:55:40 -05:00
#endif
#include "angel.h"
#include "log.h"
#include "manager.h"
#include "options.h"
#include "user_management_commands.h"
2005-07-20 10:55:40 -05:00
#ifdef __WIN__
#include "IMService.h"
2005-07-20 10:55:40 -05:00
#endif
/*
Instance Manager consists of two processes: the angel process (IM-angel),
and the manager process (IM-main). Responsibilities of IM-angel is to
monitor IM-main, and restart it in case of failure/shutdown. IM-angel is
started only if startup option '--run-as-service' is provided.
IM-main consists of several subsystems (thread sets):
- the signal handling thread
The signal thread handles user signals and propagates them to the
other threads. All other threads are accounted in the signal handler
thread Thread Registry.
- the listener
The listener listens to all sockets. There is a listening socket for
each subsystem (TCP/IP, UNIX socket).
- mysql subsystem
Instance Manager acts like an ordinary MySQL Server, but with very
restricted command set. Each MySQL client connection is handled in a
separate thread. All MySQL client connections threads constitute
mysql subsystem.
*/
static int im_main(int argc, char *argv[]);
2005-07-20 10:55:40 -05:00
#ifndef __WIN__
static struct passwd *check_user();
static bool switch_user();
2005-07-20 10:55:40 -05:00
#endif
/************************************************************************/
/**
The entry point.
*************************************************************************/
int main(int argc, char *argv[])
{
int return_value;
2005-02-05 14:04:49 +03:00
/* Initialize. */
MY_INIT(argv[0]);
log_init();
umask(0117);
srand((unsigned int) time(0));
/* Main function. */
2005-02-05 14:04:49 +03:00
log_info("IM: started.");
return_value= im_main(argc, argv);
2006-02-10 02:15:55 +03:00
log_info("IM: finished.");
2005-02-05 14:04:49 +03:00
/* Cleanup. */
Options::cleanup();
my_end(0);
return return_value;
}
/************************************************************************/
/**
Instance Manager main functionality.
*************************************************************************/
2005-07-20 10:55:40 -05:00
int im_main(int argc, char *argv[])
{
int rc;
if ((rc= Options::load(argc, argv)))
return rc;
if (Options::User_management::cmd)
return Options::User_management::cmd->execute();
#ifndef __WIN__
if (switch_user())
return 1;
return Options::Daemon::run_as_service ?
Angel::main() :
Manager::main();
#else
return Options::Service::stand_alone ?
Manager::main() :
IMService::main();
#endif
}
/**************************************************************************
OS-specific functions implementation.
**************************************************************************/
2005-07-20 10:55:40 -05:00
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
2005-02-05 14:04:49 +03:00
/************************************************************************/
/**
Change to run as another user if started with --user.
*************************************************************************/
static struct passwd *check_user()
2005-02-05 14:04:49 +03:00
{
const char *user= Options::Daemon::user;
2005-02-05 14:04:49 +03:00
struct passwd *user_info;
uid_t user_id= geteuid();
/* Don't bother if we aren't superuser */
if (user_id)
{
if (user)
{
/* Don't give a warning, if real user is same as given with --user */
user_info= getpwnam(user);
if ((!user_info || user_id != user_info->pw_uid))
log_info("One can only use the --user switch if running as root\n");
}
return NULL;
}
if (!user)
{
log_info("You are running mysqlmanager as root! This might introduce security problems. It is safer to use --user option istead.\n");
return NULL;
}
if (!strcmp(user, "root"))
return NULL; /* Avoid problem with dynamic libraries */
if (!(user_info= getpwnam(user)))
{
/* Allow a numeric uid to be used */
const char *pos;
2005-05-16 01:54:02 +04:00
for (pos= user; my_isdigit(default_charset_info, *pos); pos++)
{}
2005-02-05 14:04:49 +03:00
if (*pos) /* Not numeric id */
goto err;
if (!(user_info= getpwuid(atoi(user))))
goto err;
else
return user_info;
}
else
return user_info;
err:
log_error("Can not start under user '%s'.",
(const char *) user);
2005-02-05 14:04:49 +03:00
return NULL;
}
/************************************************************************/
/**
Switch user.
*************************************************************************/
static bool switch_user()
2005-02-05 14:04:49 +03:00
{
struct passwd *user_info= check_user();
if (!user_info)
return FALSE;
2005-02-05 14:04:49 +03:00
#ifdef HAVE_INITGROUPS
initgroups(Options::Daemon::user, user_info->pw_gid);
2005-02-05 14:04:49 +03:00
#endif
2005-02-05 14:04:49 +03:00
if (setgid(user_info->pw_gid) == -1)
{
log_error("setgid() failed");
return TRUE;
2005-02-05 14:04:49 +03:00
}
2005-02-05 14:04:49 +03:00
if (setuid(user_info->pw_uid) == -1)
{
log_error("setuid() failed");
return TRUE;
2005-02-05 14:04:49 +03:00
}
return FALSE;
}
2005-07-20 10:55:40 -05:00
#endif