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