00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <stdio.h>
00028 #include <unistd.h>
00029 #include <sys/types.h>
00030 #include <sys/wait.h>
00031 #include <signal.h>
00032
00033 #include <eyedb/eyedb.h>
00034 #include <eyedbsm/smd.h>
00035 #include <eyedblib/strutils.h>
00036 #include "SessionLog.h"
00037 #include "comp_time.h"
00038 #include "lib/compile_builtin.h"
00039
00040 using namespace eyedb;
00041 using namespace std;
00042
00043 namespace eyedb {
00044 extern void printVersion();
00045 }
00046
00047 static int
00048 usage(const char *prog)
00049 {
00050 cerr << "usage: " << prog << " ";
00051 cerr << "[-h|--help|-v|--version] [start|stop|status] [-f] [--creating-dbm] [--allow-root] ";
00052 print_common_usage(cerr, true);
00053 cerr << endl;
00054 return 1;
00055 }
00056
00057 static void help(const char *prog)
00058 {
00059 usage(prog);
00060 cerr << "\nProgram Options:\n";
00061 cerr << " start [-f] Launch the server. Set -f to force launch\n";
00062 cerr << " stop [-f] Stop the server. Set -f to force stop\n";
00063 cerr << " status Display status on the running server\n";
00064 cerr << " --creating-dbm Bootstrap option for DBM database creation\n";
00065 cerr << " --allow-root Allow running as root (not allowed by default)\n";
00066 print_common_help(cerr, true);
00067 }
00068
00069 static void
00070 check(const char *opt, int i, int argc)
00071 {
00072 if (i >= argc - 1) {
00073 fprintf(stderr, "eyedb options: missing argument after '%s'\n", opt);
00074 exit(1);
00075 }
00076 }
00077
00078 enum Command {
00079 Start = 1,
00080 Stop,
00081 CStatus
00082 };
00083
00084 static void
00085 ld_libpath_manage()
00086 {
00087 static const char ld_libpath_env[] = "LD_LIBRARY_PATH";
00088 char *ld_library_path = getenv(ld_libpath_env);
00089 char env[2048];
00090 sprintf(env, "%s=%s%s%s", ld_libpath_env,
00091 eyedb::ServerConfig::getSValue("sopath"),
00092 (ld_library_path ? ":" : ""),
00093 (ld_library_path ? ld_library_path : ""));
00094 putenv(strdup(env));
00095 }
00096
00097 static const char *sbindir;
00098 #define PIPE_SYNC
00099
00100 extern char **environ;
00101
00102 static int
00103 execute(const char *prog, const char *arg, Bool pipes)
00104 {
00105 int pid;
00106
00107 #ifdef PIPE_SYNC
00108 int pfd[2];
00109 if (pipes && pipe(pfd) < 0) {
00110 fprintf(stderr, "eyedbctl: cannot create unnamed pipes\n");
00111 return 1;
00112 }
00113 #endif
00114
00115 if ((pid = fork()) == 0) {
00116 std::string cmd = std::string(sbindir) + "/" + prog;
00117 char *argv[3];
00118
00119 argv[0] = (char *)prog;
00120 argv[1] = (char *)arg;
00121 argv[2] = 0;
00122 #ifdef PIPE_SYNC
00123 if (pipes) {
00124 close(pfd[0]);
00125 putenv(strdup((std::string("EYEDBPFD=") + str_convert((long)pfd[1])).c_str()));
00126 }
00127 #endif
00128 if (execve(cmd.c_str(), argv, environ) < 0) {
00129 fprintf(stderr, "eyedbctl: cannot execute '%s'\n", cmd.c_str());
00130 return -1;
00131 }
00132 }
00133
00134 #ifdef PIPE_SYNC
00135 if (pipes) {
00136 int status = 0;
00137 if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) {
00138 fprintf(stderr, "eyedbctl: eyedbd smd start failed\n");
00139 return 0;
00140 }
00141
00142 if (status)
00143 return -1;
00144 }
00145 #endif
00146 return pid;
00147 }
00148
00149 static int
00150 startServer(int argc, char *argv[], const char *smdport)
00151 {
00152 #ifdef HAVE_EYEDBSMD
00153 smdcli_conn_t *conn = smdcli_open(smd_get_port());
00154 if (conn) {
00155 if (smdcli_declare(conn) < 0)
00156 return 1;
00157 smdcli_close(conn);
00158 conn = 0;
00159 }
00160 else if (execute("eyedbsmd", (std::string("--port=") + smdport).c_str(), True) < 0)
00161 return 1;
00162 #endif
00163
00164 #ifdef PIPE_SYNC
00165 int pfd[2];
00166 if (pipe(pfd) < 0) {
00167 fprintf(stderr, "eyedbctl: cannot create unnamed pipes\n");
00168 return 1;
00169 }
00170 #endif
00171
00172 int pid;
00173
00174 if ((pid = fork()) == 0) {
00175 ld_libpath_manage();
00176 std::string cmd = std::string(sbindir) + "/eyedbd";
00177 std::string s = std::string("eyedbd");
00178
00179 argv[0] = (char *)s.c_str();
00180 #ifdef PIPE_SYNC
00181 close(pfd[0]);
00182 putenv(strdup((std::string("EYEDBPFD=") + str_convert((long)pfd[1])).c_str()));
00183 #endif
00184 if (execve(cmd.c_str(), argv, environ) < 0) {
00185 kill(getppid(), SIGINT);
00186 fprintf(stderr, "eyedbctl: cannot execute '%s'\n", cmd.c_str());
00187 }
00188
00189 exit(1);
00190 }
00191
00192 if (pid < 0)
00193 return 1;
00194
00195 close(pfd[1]);
00196 int status = 0;
00197
00198 #ifdef PIPE_SYNC
00199 if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) {
00200 fprintf(stderr, "eyedbctl: eyedbd daemon start failed\n");
00201 return 1;
00202 }
00203
00204 if (!status)
00205 fprintf(stderr, "Starting EyeDB Server\n"
00206 " Version V%s\n"
00207 " Compiled %s\n"
00208 " Architecture %s\n"
00209 " Program Pid %d\n",
00210 eyedb::getVersion(),
00211 getCompilationTime(),
00212 Architecture::getArchitecture()->getArch(),
00213 pid);
00214 #endif
00215
00216 return status;
00217 }
00218
00219 static void unlink_port(const char *port)
00220 {
00221 if (*port == '/' || strchr(port, ':') == 0) {
00222 unlink(port);
00223 }
00224 }
00225
00226 static void unlink_ports(const char *smdport, const char *_listen)
00227 {
00228 char *listen = strdup(_listen);
00229 char *p = listen;
00230
00231 for (;;) {
00232 char *q = strchr(p, ',');
00233 if (q)
00234 *q = 0;
00235 unlink_port(p);
00236 if (!q)
00237 break;
00238 p = q + 1;
00239 }
00240
00241 #ifdef HAVE_EYEDBSMD
00242 unlink(smdport);
00243 #endif
00244 }
00245
00246 static void make_host_port(const char *_listen, const char *&host,
00247 const char *&port)
00248 {
00249 char *listen = strdup(_listen);
00250
00251 char *p;
00252 if (p = strchr(listen, ','))
00253 *p = 0;
00254
00255 if (p = strchr(listen, ':')) {
00256 *p = 0;
00257 host = listen;
00258 port = p+1;
00259 }
00260 else {
00261 host = "localhost";
00262 port = listen;
00263 }
00264 }
00265
00266 static int checkPostInstall(Bool creatingDbm)
00267 {
00268 if (!creatingDbm) {
00269 const char *dbm = Database::getDefaultServerDBMDB();
00270 if (!dbm || access(dbm, R_OK)) {
00271 fprintf(stderr, "\nThe EYEDBDBM database file '%s' is not accessible\n", dbm);
00272 fprintf(stderr, "Did you run the post install script 'eyedb-postinstall.sh' ?\n");
00273 fprintf(stderr, "If yes, check your configuration or launch eyedbctl with option --creating-dbm\n");
00274 return 1;
00275 }
00276 }
00277
00278 return 0;
00279 }
00280
00281 static int checkRoot( Bool allowRoot)
00282 {
00283 if (!allowRoot) {
00284 if (!getuid()) {
00285 fprintf(stderr, "\nLaunching EyeDB server as root is not allowed for security.\n");
00286 fprintf(stderr, "You can overide this by launching eyedbctl with option --allow-root\n");
00287 return 1;
00288 }
00289 }
00290
00291 return 0;
00292 }
00293
00294 int
00295 main(int argc, char *argv[])
00296 {
00297 const char *listen, *smdport, *s;
00298 eyedbsm::Status status;
00299 Bool force = False;
00300 Bool creatingDbm = False;
00301 Bool allowRoot = False;
00302 string sv_host, sv_port;
00303
00304 string sv_listen;
00305 try {
00306 if (argc < 2)
00307 return usage(argv[0]);
00308
00309 Command cmd;
00310
00311 if (!strcmp(argv[1], "start"))
00312 cmd = Start;
00313 else if (!strcmp(argv[1], "stop"))
00314 cmd = Stop;
00315 else if (!strcmp(argv[1], "status"))
00316 cmd = CStatus;
00317 else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
00318 help(argv[0]);
00319 return 0;
00320 }
00321 else if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
00322 eyedb::printVersion();
00323 return 0;
00324 }
00325 else
00326 return usage(argv[0]);
00327
00328 eyedb::init(argc, argv, &sv_listen, false);
00329
00330 listen = sv_listen.c_str();
00331
00332 eyedb::Exception::setMode(eyedb::Exception::StatusMode);
00333
00334 for (int i = 2; i < argc; i++) {
00335 char *s = argv[i];
00336 if (!strcmp(s, "-f"))
00337 force = True;
00338 else if (!strcmp(s, "--creating-dbm"))
00339 creatingDbm = True;
00340 else if (!strcmp(s, "--allow-root"))
00341 allowRoot = True;
00342 else
00343 break;
00344 }
00345
00346 if (!*listen && (s = eyedb::ServerConfig::getSValue("listen")))
00347 listen = s;
00348
00349 smdport = smd_get_port();
00350
00351 if (cmd == Start && force) {
00352 unlink_ports(smdport, listen);
00353 }
00354
00355 sbindir = ServerConfig::getSValue("@sbindir");
00356
00357 int ac;
00358 char **av;
00359
00360 if (cmd == Start) {
00361 if (checkRoot( allowRoot))
00362 return 1;
00363
00364 if (checkPostInstall(creatingDbm))
00365 return 1;
00366
00367 int st = force + creatingDbm + allowRoot;
00368
00369 ac = argc - st;
00370 av = &argv[st+1];
00371 }
00372
00373 const char *host, *port;
00374 make_host_port(listen, host, port);
00375
00376 SessionLog sesslog(host, port, eyedb::ServerConfig::getSValue("tmpdir"),
00377 True);
00378
00379
00380
00381 if (sesslog.getStatus()) {
00382 if (cmd == Start)
00383 return startServer(ac, av, smdport);
00384 if (sesslog.getStatus()->getStatus() == IDB_CONNECTION_LOG_FILE_ERROR) {
00385 cerr << "No EyeDB Server is running on " << host << ":" << port << endl;
00386 return 1;
00387 }
00388 sesslog.getStatus()->print();
00389 return 1;
00390 }
00391
00392 if (cmd == Start)
00393 return startServer(ac, av, smdport);
00394
00395 if (cmd == Stop) {
00396 Status status = sesslog.stopServers(force);
00397 if (status) {
00398 status->print();
00399 return 1;
00400 }
00401
00402 #ifndef HAVE_EYEDBSMD
00403 return 0;
00404 #else
00405 smdcli_conn_t *conn = smdcli_open(smd_get_port());
00406 if (!conn) {
00407 fprintf(stderr, "cannot connect to eyedbsmd daemon\n");
00408 return 1;
00409 }
00410
00411 int r = smdcli_stop(conn);
00412 smdcli_close(conn);
00413 conn = 0;
00414 return r;
00415 #endif
00416 }
00417
00418 sesslog.display(stdout, force);
00419 }
00420 catch(Exception &e) {
00421 cerr << e << flush;
00422 return 1;
00423 }
00424
00425 return 0;
00426 }