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 <stdio.h>
00026 #include <unistd.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <eyedb/eyedb.h>
00030 #include "base_p.h"
00031 #include "eyedb/internals/ObjectHeader.h"
00032 #include <eyedblib/rpc_lib.h>
00033 #include <eyedbsm/smd.h>
00034 #include "SessionLog.h"
00035 #include <eyedblib/connman.h>
00036 #include "eyedblib/log.h"
00037 #include "eyedblib/butils.h"
00038 #include "eyedb/Log.h"
00039 #include "GetOpt.h"
00040
00041 #include "serv_lib.h"
00042 #include "kernel.h"
00043
00044
00045
00046 using namespace std;
00047
00048 namespace eyedb {
00049 extern void (*garbage_handler)(void);
00050 extern void printVersion();
00051 }
00052
00053 #ifdef RPC_TIMEOUT
00054 extern void (*settimeout)(int);
00055 #endif
00056 namespace eyedbsm {
00057 extern Boolean backend;
00058 }
00059
00060 using namespace eyedb;
00061
00062 static Bool nod;
00063
00064
00065
00066 static int
00067 get_opts(int argc, char *argv[],
00068 const char **accessfile,
00069 const char **datdir,
00070 const char **sesslogdev,
00071 int *sessloglevel,
00072 int *nofork)
00073 {
00074 int i;
00075 const char *s;
00076
00077 *accessfile = eyedb::ServerConfig::getSValue("access_file");
00078 *nofork = 0;
00079 *sesslogdev = 0;
00080 *sessloglevel = 0;
00081
00082 #ifndef NO_DATDIR
00083 *datdir = 0;
00084 #else
00085 *datdir = "";
00086 #endif
00087
00088 static const std::string access_file_opt = "access-file";
00089 static const std::string datdir_opt = "databasedir";
00090 static const std::string nod_opt = "nod";
00091 static const std::string sesslogdev_opt = "sesslogdev";
00092 static const std::string sessloglevel_opt = "sessloglevel";
00093 static const std::string help_opt = "help";
00094
00095 Option opts[] = {
00096 Option(access_file_opt, OptionStringType(),
00097 Option::MandatoryValue, OptionDesc("Access file", "ACCESS_FILE")),
00098 #ifndef NO_DATDIR
00099 Option(datdir_opt, OptionStringType(),
00100 Option::MandatoryValue, OptionDesc("Default datafile directory", "DATDIR")),
00101 #endif
00102 Option(nod_opt, OptionBoolType(),
00103 0, OptionDesc("No daemon: does not close fd 0, 1 & 2")),
00104 Option('h', help_opt, OptionBoolType(),
00105 0, OptionDesc("Display this message"))
00106 };
00107
00108 GetOpt getopt(argv[0], opts, sizeof(opts)/sizeof(opts[0]));
00109
00110 if (!getopt.parse(argc, argv)) {
00111 print_standard_usage(getopt, "", std::cerr, true);
00112
00113 return 1;
00114 }
00115
00116 GetOpt::Map &map = getopt.getMap();
00117
00118 if (map.find(help_opt) != map.end()) {
00119 print_standard_help(getopt, vector<string>(), std::cerr, true);
00120
00121 return 1;
00122 }
00123
00124 if (map.find(access_file_opt) != map.end())
00125 *accessfile = strdup(map[access_file_opt].value.c_str());
00126
00127 #ifndef NO_DATDIR
00128 if (map.find(datdir_opt) != map.end())
00129 *datdir = strdup(map[datdir_opt].value.c_str());
00130 #endif
00131
00132 if (map.find(nod_opt) != map.end())
00133 nod = True;
00134
00135 if (map.find(sesslogdev_opt) != map.end())
00136 *sesslogdev = strdup(map[sesslogdev_opt].value.c_str());
00137
00138 if (map.find(sessloglevel_opt) != map.end())
00139 *sessloglevel = ((OptionIntType *)map[sessloglevel_opt].type)->
00140 getIntValue(map[sessloglevel_opt].value);
00141
00142 #ifndef NO_DATDIR
00143 if (!*datdir) {
00144 if (s = eyedb::ServerConfig::getSValue("databasedir"))
00145 *datdir = strdup(s);
00146 else {
00147 fprintf(stderr, "configuration variable databasedir is not set\n");
00148 exit(1);
00149 }
00150 }
00151 #endif
00152
00153 return 0;
00154 }
00155
00156 static SessionLog *sesslog;
00157
00158 void rpc_unlink_socket();
00159
00160 static void
00161 _quit_handler(void *xpid, int)
00162 {
00163 if (*(int *)xpid == rpc_getpid()) {
00164 sesslog->remove();
00165 rpc_unlink_socket();
00166 }
00167 }
00168
00169 static int
00170 notice(int status)
00171 {
00172 const char *s;
00173 if (s = getenv("EYEDBPFD")) {
00174 int pfd = atoi(s);
00175 if (pfd > 0) {
00176 write(pfd, &status, sizeof(status));
00177 close(pfd);
00178 }
00179 }
00180
00181 return status;
00182 }
00183
00184 static unsigned int get_ports(const char *ports[], const char *hosts[],
00185 const char *_listen)
00186 {
00187 if (!_listen)
00188 return 0;
00189
00190 char *listen = strdup(_listen);
00191 unsigned int nlisten = 0;
00192 for (;;) {
00193 ports[nlisten++] = listen;
00194 listen = strchr(listen, ',');
00195 if (!listen)
00196 break;
00197 *listen++ = 0;
00198 }
00199
00200 for (int n = 0; n < nlisten; n++) {
00201 const char *p = strchr(ports[n], ':');
00202 if (p) {
00203 *(char *)p = 0;
00204 hosts[n] = ports[n];
00205 ports[n] = p + 1;
00206 }
00207 else {
00208 hosts[n] = "localhost";
00209 }
00210 }
00211
00212
00213 return nlisten;
00214 }
00215
00216 int
00217 main(int argc, char *argv[])
00218 {
00219 rpc_Server *server;
00220 rpc_PortHandle *port[32];
00221 const char *ports[32];
00222 const char *hosts[32];
00223 eyedbsm::Status status;
00224 const char *hostname;
00225 const char *accessfile, *datdir;
00226 const char *listen;
00227 const char *sesslogdev;
00228 int sessloglevel;
00229 unsigned int nlisten;
00230
00231 int nofork;
00232
00233 string sv_listen;
00234
00235 try {
00236 eyedb::init(argc, argv, &sv_listen, true);
00237
00238 listen = sv_listen.c_str();
00239
00240 server = rpcBeInit();
00241
00242 garbage_handler = GARBAGE;
00243 #ifdef RPC_TIMEOUT
00244 settimeout = rpc_setTimeOut;
00245 #endif
00246
00247 eyedbsm::backend = eyedbsm::True;
00248
00249 if (get_opts(argc, argv, &accessfile, &datdir, &sesslogdev,
00250 &sessloglevel, &nofork))
00251 return notice(1);
00252
00253 rpc_setProgName(argv[0]);
00254
00255 if (!*listen)
00256 listen = eyedb::ServerConfig::getSValue("listen");
00257
00258 nlisten = get_ports(ports, hosts, listen);
00259
00260 for (int n = 0; n < nlisten; n++) {
00261 if (!eyedblib::is_number(ports[n]) && strcmp(hosts[n], "localhost")) {
00262 fprintf(stderr, "eyedbd: cannot specify host '%s' for named pipe '%s'\n",
00263 hosts[n], ports[n]);
00264 return 1;
00265 }
00266 }
00267
00268 if (rpc_connman_init(accessfile))
00269 return notice(1);
00270
00271 if (!nlisten) {
00272 fprintf(stderr, "eyedbd: at least one port must be set.\n");
00273 return notice(1);
00274 }
00275
00276 for (int i = 0; i < nlisten; i++)
00277 if (rpc_portOpen(server, hosts[i], ports[i], &port[i]))
00278 return notice(1);
00279
00280 int *pid = new int;
00281 *pid = getpid();
00282 rpc_setQuitHandler(_quit_handler, pid);
00283
00284 const char *sv_tmpdir = eyedb::ServerConfig::getSValue("tmpdir");
00285
00286 if (!sv_tmpdir)
00287 sv_tmpdir = "/tmp";
00288
00289 std::string logdir = sv_tmpdir;
00290
00291 eyedb::Exception::setMode(eyedb::Exception::StatusMode);
00292
00293 sesslog = new SessionLog(logdir.c_str(), eyedb::getVersion(),
00294 nlisten, hosts, ports,
00295 datdir, sesslogdev, sessloglevel);
00296
00297 #ifndef NO_DATDIR
00298 IDB_init(datdir, 0 , sesslog, 0 );
00299 #else
00300 IDB_init(0, 0 , sesslog, 0 );
00301 #endif
00302
00303 if (sesslog->getStatus()) {
00304 sesslog->getStatus()->print();
00305 return notice(1);
00306 }
00307
00308 (void)notice(0);
00309
00310 if (!nod) {
00311 close(0);
00312 if (!Log::getLog() || strcmp(Log::getLog(), "stdout"))
00313 close(1);
00314 if (!Log::getLog() || strcmp(Log::getLog(), "stderr"))
00315 close(2);
00316 }
00317
00318 rpc_serverMainLoop(server, port, nlisten);
00319 }
00320 catch(Exception &e) {
00321 cerr << e << flush;
00322 return 1;
00323 }
00324 catch(int status) {
00325 return status;
00326 }
00327 return 0;
00328 }