1 /* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15
16 #include <ndb_global.h> /* Needed for mkdir(2) */
17 #include <my_sys.h>
18 #include <my_getopt.h>
19 #include <mysql_version.h>
20 #include <ndb_version.h>
21
22 #include "CPCD.hpp"
23 #include "APIService.hpp"
24 #include <NdbMain.h>
25 #include <NdbSleep.h>
26 #include <BaseString.hpp>
27 #include <logger/Logger.hpp>
28 #include <logger/FileLogHandler.hpp>
29 #include <logger/SysLogHandler.hpp>
30
31 #include "common.hpp"
32
33 static const char *work_dir = CPCD_DEFAULT_WORK_DIR;
34 static int unsigned port;
35 static int use_syslog;
36 static const char *logfile = NULL;
37 static const char *user = 0;
38
39 static struct my_option my_long_options[] =
40 {
41 { "work-dir", 'w', "Work directory",
42 &work_dir, &work_dir, 0,
43 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
44 { "port", 'p', "TCP port to listen on",
45 &port, &port, 0,
46 GET_INT, REQUIRED_ARG, CPCD_DEFAULT_TCP_PORT, 0, 0, 0, 0, 0 },
47 { "syslog", 'S', "Log events to syslog",
48 &use_syslog, &use_syslog, 0,
49 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
50 { "logfile", 'L', "File to log events to",
51 &logfile, &logfile, 0,
52 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
53 { "debug", 'D', "Enable debug mode",
54 &debug, &debug, 0,
55 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
56 { "user", 'u', "Run as user",
57 &user, &user, 0,
58 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
59 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
60 };
61
62 static my_bool
get_one_option(int optid,const struct my_option * opt,char * argument)63 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
64 char *argument)
65 {
66 return 0;
67 }
68
69 static CPCD * g_cpcd = 0;
70 #if 0
71 extern "C" static void sig_child(int signo, siginfo_t*, void*);
72 #endif
73
74 const char *progname = "ndb_cpcd";
75
main(int argc,char ** argv)76 int main(int argc, char** argv){
77 const char *load_default_groups[]= { "ndb_cpcd",0 };
78 MY_INIT(argv[0]);
79
80 load_defaults("ndb_cpcd",load_default_groups,&argc,&argv);
81 if (handle_options(&argc, &argv, my_long_options, get_one_option)) {
82 print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
83 puts("");
84 my_print_help(my_long_options);
85 my_print_variables(my_long_options);
86 exit(1);
87 }
88
89 logger.setCategory(progname);
90 logger.enable(Logger::LL_ALL);
91
92 if(debug)
93 logger.createConsoleHandler();
94
95 if(user && runas(user) != 0){
96 logger.critical("Unable to change user: %s", user);
97 _exit(1);
98 }
99
100 if(logfile != NULL){
101 BaseString tmp;
102 if(logfile[0] != '/')
103 tmp.append(work_dir);
104 tmp.append(logfile);
105 logger.addHandler(new FileLogHandler(tmp.c_str()));
106 }
107
108 if(use_syslog)
109 logger.addHandler(new SysLogHandler());
110
111 logger.info("Starting");
112
113 CPCD cpcd;
114 g_cpcd = &cpcd;
115
116 /* XXX This will probably not work on !unix */
117 int err = mkdir(work_dir, S_IRWXU | S_IRGRP | S_IROTH);
118 if(err != 0) {
119 switch(errno) {
120 case EEXIST:
121 break;
122 default:
123 fprintf(stderr, "Cannot mkdir %s: %s\n", work_dir, strerror(errno));
124 exit(1);
125 }
126 }
127
128 if(strlen(work_dir) > 0){
129 logger.debug("Changing dir to '%s'", work_dir);
130 if((err = chdir(work_dir)) != 0){
131 fprintf(stderr, "Cannot chdir %s: %s\n", work_dir, strerror(errno));
132 exit(1);
133 }
134 }
135
136 cpcd.loadProcessList();
137
138 SocketServer * ss = new SocketServer();
139 CPCDAPIService * serv = new CPCDAPIService(cpcd);
140 unsigned short real_port= port; // correct type
141 if(!ss->setup(serv, &real_port)){
142 logger.critical("Cannot setup server: %s", strerror(errno));
143 sleep(1);
144 delete ss;
145 delete serv;
146 return 1;
147 }
148
149 ss->startServer();
150
151 {
152 signal(SIGPIPE, SIG_IGN);
153 signal(SIGCHLD, SIG_IGN);
154 #if 0
155 struct sigaction act;
156 act.sa_handler = 0;
157 act.sa_sigaction = sig_child;
158 sigemptyset(&act.sa_mask);
159 act.sa_flags = SA_SIGINFO;
160 sigaction(SIGCHLD, &act, 0);
161 #endif
162 }
163
164 logger.debug("Start completed");
165 while(true) NdbSleep_MilliSleep(1000);
166
167 delete ss;
168 return 0;
169 }
170
171 #if 0
172 extern "C"
173 void
174 sig_child(int signo, siginfo_t* info, void*){
175 printf("signo: %d si_signo: %d si_errno: %d si_code: %d si_pid: %d\n",
176 signo,
177 info->si_signo,
178 info->si_errno,
179 info->si_code,
180 info->si_pid);
181
182 }
183 #endif
184