You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
freshtomato-arm/release/src-rt-6.x.4708/router/rc/mysql.c

417 lines
13 KiB
C

/*
* mysql.c
*
* Copyright (C) 2014 bwq518, Hyzoom
* Fixes/updates (C) 2018 - 2022 pedro
*
*/
#include "rc.h"
#define mysql_etc_dir "/etc/mysql"
#define mysql_conf_link "/etc/my.cnf"
#define mysql_conf mysql_etc_dir"/my.cnf"
#define mysql_start_script mysql_etc_dir"/start_mysql.sh"
#define mysql_stop_script mysql_etc_dir"/stop_mysql.sh"
#define mysql_passwd mysql_etc_dir"/setpasswd.sql"
#define mysql_anyhost mysql_etc_dir"/setanyhost.sql"
#define mysql_child_pid mysql_etc_dir"/child.pid"
#define mysql_pid "/var/run/mysqld.pid"
#define mysql_log "/var/log/mysql.log"
#define mysql_dflt_dir "/tmp/mysql"
/* needed by logmsg() */
#define LOGMSG_DISABLE DISABLE_SYSLOG_OSM
#define LOGMSG_NVDEBUG "mysql_debug"
static void setup_mysql_watchdog(void)
{
FILE *fp;
char buffer[64], buffer2[64];
int nvi;
if ((nvi = nvram_get_int("mysql_check_time")) > 0) {
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), mysql_etc_dir"/watchdog.sh");
if ((fp = fopen(buffer, "w"))) {
fprintf(fp, "#!/bin/sh\n"
"[ -z \"$(pidof mysqld)\" -a \"$(nvram get g_upgrade)\" != \"1\" -a \"$(nvram get g_reboot)\" != \"1\" ] && {\n"
" logger -t mysql-watchdog mysqld stopped? Starting...\n"
" service mysql restart\n"
"}\n");
fclose(fp);
chmod(buffer, (S_IRUSR | S_IWUSR | S_IXUSR));
memset(buffer2, 0, sizeof(buffer2));
snprintf(buffer2, sizeof(buffer2), "*/%d * * * * %s", nvi, buffer);
eval("cru", "a", "CheckMySQL", buffer2);
}
}
}
void start_mysql(int force)
{
FILE *fp;
char pbi[128];
char ppr[64];
char pdatadir[256], ptmpdir[256];
char full_datadir[256], full_tmpdir[256], basedir[256];
char tmp1[256], tmp2[256];
int n;
pid_t pidof_child = 0;
unsigned int new_install = 0;
char *nginx_docroot = nvram_safe_get("nginx_docroot");
unsigned int anyhost = nvram_get_int("mysql_allow_anyhost");
/* only if enabled or forced */
if (!nvram_get_int("mysql_enable") && force == 0)
return;
if (serialize_restart("mysqld", 1))
return;
memset(tmp1, 0, sizeof(tmp1));
if (f_read_string(mysql_child_pid, tmp1, sizeof(tmp1)) > 0 && atoi(tmp1) > 0 && ppid(atoi(tmp1)) > 0) { /* fork is still up */
logmsg(LOG_WARNING, "%s: another process (PID: %s) still up, aborting ...", __FUNCTION__, tmp1);
return;
}
logmsg(LOG_INFO, "starting mysqld ...");
if (nvram_match("mysql_binary", "internal"))
strlcpy(pbi, "/usr/bin", sizeof(pbi));
else if (nvram_match("mysql_binary", "optware"))
strlcpy(pbi, "/opt/bin", sizeof(pbi));
else
strlcpy(pbi, nvram_safe_get("mysql_binary_custom"), sizeof(pbi));
if (pbi[strlen(pbi) - 1] == '/')
pbi[strlen(pbi) - 1] = '\0';
splitpath(pbi, basedir, tmp1);
/* generate download saved path based on USB partition (mysql_dlroot) and directory name (mysql_datadir) */
if (nvram_get_int("mysql_usb_enable")) {
tmp1[0] = 0;
tmp2[0] = 0;
strlcpy(tmp1, nvram_safe_get("mysql_dlroot"), sizeof(tmp1));
trimstr(tmp1);
if (tmp1[0] != '/') {
memset(tmp2, 0, sizeof(tmp2));
snprintf(tmp2, sizeof(tmp2), "/%s", tmp1);
strlcpy(tmp1, tmp2, sizeof(tmp1));
}
strlcpy(ppr, tmp1, sizeof(ppr));
if (ppr[strlen(ppr) - 1] == '/')
ppr[strlen(ppr) - 1] = 0;
if (strlen(ppr) == 0) {
logmsg(LOG_ERR, "No mounted USB partition found. You need to mount the USB drive first");
return;
}
}
else
strlcpy(ppr, mysql_dflt_dir, sizeof(ppr));
strlcpy(pdatadir, nvram_safe_get("mysql_datadir"), sizeof(pdatadir));
trimstr(pdatadir);
if (pdatadir[strlen(pdatadir) - 1] == '/')
pdatadir[strlen(pdatadir) - 1] = 0;
if (strlen(pdatadir) == 0) {
strlcpy(pdatadir, "data", sizeof(pdatadir));
nvram_set("mysql_dir", "data");
}
memset(full_datadir, 0, sizeof(full_datadir));
if (pdatadir[0] == '/')
snprintf(full_datadir, sizeof(full_datadir), "%s%s", ppr, pdatadir);
else
snprintf(full_datadir, sizeof(full_datadir), "%s/%s", ppr, pdatadir);
strlcpy(ptmpdir, nvram_safe_get("mysql_tmpdir"), sizeof(ptmpdir));
trimstr(ptmpdir);
if (ptmpdir[strlen(ptmpdir) - 1] == '/')
ptmpdir[strlen(ptmpdir) - 1] = 0;
if (strlen(ptmpdir) == 0) {
strlcpy (ptmpdir, "tmp", sizeof(ptmpdir));
nvram_set("mysql_tmpdir", "tmp");
}
memset(full_tmpdir, 0, sizeof(full_tmpdir));
if (ptmpdir[0] == '/')
snprintf(full_tmpdir, sizeof(full_tmpdir), "%s%s", ppr, ptmpdir);
else
snprintf(full_tmpdir, sizeof(full_tmpdir), "%s/%s", ppr, ptmpdir);
mkdir_if_none(mysql_etc_dir);
/* config file */
if (!(fp = fopen(mysql_conf, "w"))) {
logerr(__FUNCTION__, __LINE__, mysql_conf);
return;
}
fprintf(fp, "[client]\n"
"port = %s\n"
"socket = /var/run/mysqld.sock\n\n"
"[mysqld]\n"
"user = root\n"
"socket = /var/run/mysqld.sock\n"
"port = %s\n"
"basedir = %s\n\n"
"datadir = %s\n"
"tmpdir = %s\n\n"
"skip-external-locking\n",
nvram_safe_get("mysql_port"),
nvram_safe_get("mysql_port"),
basedir,
full_datadir,
full_tmpdir);
if (nvram_get_int("mysql_allow_anyhost"))
fprintf(fp, "bind-address = 0.0.0.0\n");
else
fprintf(fp, "bind-address = 127.0.0.1\n");
/* disable innodb engine */
fprintf(fp, "default-storage-engine=MYISAM\n"
"innodb=OFF\n");
fprintf(fp, "key_buffer_size = %sM\n"
"max_allowed_packet = %sM\n"
"thread_stack = %sK\n"
"thread_cache_size = %s\n\n"
"table_open_cache = %s\n"
"sort_buffer_size = %sK\n"
"read_buffer_size = %sK\n"
"read_rnd_buffer_size = %sK\n"
"query_cache_size = %sM\n"
"max_connections = %s\n\n"
"#The following items are from mysql_server_custom\n"
"%s\n"
"#end of mysql_server_custom\n\n"
"[mysqldump]\n"
"quick\nquote-names\n"
"max_allowed_packet = 16M\n"
"[mysql]\n\n"
"[isamchk]\n"
"key_buffer_size = 8M\n"
"sort_buffer_size = 8M\n\n",
nvram_safe_get("mysql_key_buffer"),
nvram_safe_get("mysql_max_allowed_packet"),
nvram_safe_get("mysql_thread_stack"),
nvram_safe_get("mysql_thread_cache_size"),
nvram_safe_get("mysql_table_open_cache"),
nvram_safe_get("mysql_sort_buffer_size"),
nvram_safe_get("mysql_read_buffer_size"),
nvram_safe_get("mysql_read_rnd_buffer_size"),
nvram_safe_get("mysql_query_cache_size"),
nvram_safe_get("mysql_max_connections"),
nvram_safe_get("mysql_server_custom"));
fclose(fp);
chmod(mysql_conf, 0644);
unlink(mysql_conf_link);
symlink(mysql_conf, mysql_conf_link);
/* fork new process */
if (fork() != 0) /* foreground process */
return;
pidof_child = getpid();
/* write child pid to a file */
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%d", pidof_child);
f_write_string(mysql_child_pid, tmp1, 0, 0);
/* wait a given time for partition to be mounted, etc */
n = atoi(nvram_safe_get("mysql_sleep"));
if (n > 0)
sleep(n);
/* clean mysql_log */
system("/bin/rm -f "mysql_log);
f_write(mysql_log, NULL, 0, 0, 0644);
/* check for datadir */
if (!d_exists(full_datadir)) {
logmsg(LOG_INFO, "datadir in %s doesn't exist, creating ...", ppr);
if (mkdir(full_datadir, 0755) == 0)
logmsg(LOG_INFO, "created successfully");
else {
logmsg(LOG_ERR, "create failed, aborting ...");
goto END;
}
}
/* check for tmpdir */
if (!d_exists(full_tmpdir)) {
logmsg(LOG_INFO, "tmpdir in %s doesn't exist, creating ...", ppr);
if (mkdir(full_tmpdir, 0755) == 0)
logmsg(LOG_INFO, "created successfully");
else {
logmsg(LOG_ERR, "create failed, aborting ...");
goto END;
}
}
/* check for tables_priv.MYD */
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysql/tables_priv.MYD", full_datadir);
if (!f_exists(tmp1)) {
new_install = 1;
logmsg(LOG_INFO, "tables_priv.MYD not found - it's a new MySQL installation");
f_write_string(mysql_log, "=========Found NO tables_priv.MYD====================", FW_APPEND | FW_NEWLINE, 0);
f_write_string(mysql_log, "This is new installed MySQL.", FW_APPEND | FW_NEWLINE, 0);
}
/* initialize DB? */
if (nvram_get_int("mysql_init_priv") || new_install == 1) {
logmsg(LOG_INFO, "initializing privileges table ...");
f_write_string(mysql_log, "=========mysql_install_db====================", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysql_install_db --user=root --force >> %s 2>&1", pbi, mysql_log);
system(tmp1);
logmsg(LOG_DEBUG, "*** %s: privileges table successfully initialized", __FUNCTION__);
nvram_set("mysql_init_priv", "0");
nvram_commit();
}
/* initialize root password? */
if (nvram_get_int("mysql_init_rootpass") || new_install == 1) {
logmsg(LOG_INFO, "(re-)initializing root password ...");
f_write_string(mysql_log, "=========mysqld skip-grant-tables==================", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysqld --skip-grant-tables --skip-networking --pid-file=%s >> %s 2>&1 &", pbi, mysql_pid, mysql_log);
system(tmp1);
sleep(2);
if (f_exists(mysql_passwd))
unlink(mysql_passwd);
f_write_string(mysql_passwd, "use mysql;", FW_CREATE | FW_NEWLINE, 0644);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "update user set password=password('%s') where user='root';", nvram_safe_get("mysql_passwd"));
f_write_string(mysql_passwd, tmp1, FW_APPEND | FW_NEWLINE, 0);
f_write_string(mysql_passwd, "flush privileges;", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "=========mysql < %s====================", mysql_passwd);
f_write_string(mysql_log, tmp1, FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysql < %s >> %s", pbi, mysql_passwd, mysql_log);
system(tmp1);
f_write_string(mysql_log, "=========mysqldadmin shutdown====================", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysqladmin -uroot -p\"%s\" --shutdown_timeout=3 shutdown >> %s 2>&1", pbi, nvram_safe_get("mysql_passwd"), mysql_log);
system(tmp1);
killall_tk_period_wait("mysqld", 50);
sleep(1);
system("/bin/rm -f "mysql_pid" "mysql_passwd);
logmsg(LOG_DEBUG, "*** %s: root password successfully (re-)initialized", __FUNCTION__);
nvram_set("mysql_init_rootpass", "0");
nvram_commit();
}
f_write_string(mysql_log, "=========mysqld startup====================", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysqld --pid-file=%s >> %s 2>&1 &", pbi, mysql_pid, mysql_log);
system(tmp1);
if (anyhost == 1) {
sleep(3);
if (f_exists(mysql_anyhost))
unlink(mysql_anyhost);
f_write_string(mysql_anyhost, "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%%' WITH GRANT OPTION;", FW_CREATE | FW_NEWLINE, 0644);
f_write_string(mysql_anyhost, "flush privileges;", FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "=========mysql < %s==================== >> %s", mysql_anyhost, mysql_log);
f_write_string(mysql_log, tmp1, FW_APPEND | FW_NEWLINE, 0);
memset(tmp1, 0, sizeof(tmp1));
snprintf(tmp1, sizeof(tmp1), "%s/mysql -uroot -p\"%s\" < %s >> %s 2>&1", pbi, nvram_safe_get("mysql_passwd"), mysql_anyhost, mysql_log);
system(tmp1);
system("/bin/rm -f "mysql_anyhost);
}
eval("mkdir", "-p", nginx_docroot);
eval("cp", "-p", "/www/adminer.php", nginx_docroot);
sleep(1);
END:
if (pidof("mysqld") > 0) {
logmsg(LOG_INFO, "mysqld started");
setup_mysql_watchdog();
unlink(mysql_child_pid);
}
else {
logmsg(LOG_ERR, "starting mysqld failed - check configuration ...");
unlink(mysql_child_pid);
stop_mysql();
}
/* terminate the child */
exit(0);
}
void stop_mysql(void)
{
pid_t pid;
char pbi[128], buf[512];
int m = atoi(nvram_safe_get("mysql_sleep")) + 70;
if (serialize_restart("mysqld", 0))
return;
if ((pid = pidof("mysqld")) > 0)
logmsg(LOG_INFO, "terminating mysqld ...");
else
return;
eval("cru", "d", "CheckMySQL");
/* wait for child of start_mysql to finish (if any) */
memset(buf, 0, sizeof(buf));
while (f_read_string(mysql_child_pid, buf, sizeof(buf)) > 0 && atoi(buf) > 0 && ppid(atoi(buf)) > 0 && (m-- > 0)) {
logmsg(LOG_DEBUG, "*** %s: waiting for child process of start_mysql to end, %d secs left ...", __FUNCTION__, m);
sleep(1);
}
if (nvram_match("mysql_binary", "internal"))
strlcpy(pbi, "/usr/bin", sizeof(pbi));
else if (nvram_match("mysql_binary", "optware"))
strlcpy(pbi, "/opt/bin", sizeof(pbi));
else
strlcpy(pbi, nvram_safe_get("mysql_binary_custom"), sizeof(pbi));
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%s/mysqladmin -uroot -p\"%s\" --shutdown_timeout=3 shutdown", pbi, nvram_safe_get("mysql_passwd"));
system(buf);
killall_and_waitfor("mysqld", 10, 80);
if (pid > 0)
logmsg(LOG_INFO, "mysqld stopped");
/* clean-up */
system("/bin/rm -f "mysql_pid);
unlink(mysql_conf_link);
system("/bin/rm -rf "mysql_etc_dir);
}