UserThread.cc

00001 // ----------------------------------------------------------------------^
00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone
00003 // (mailto: <gcalderone@ifc.inaf.it>)
00004 // 
00005 // This file is part of MCS.
00006 // 
00007 // MCS is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 // 
00012 // MCS is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU General Public License
00018 // along with MCS; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 // 
00021 // ----------------------------------------------------------------------$
00022 // LN
00023 //#include "malloc.h"
00024 #if HAVE_MALLOC
00025 #include <malloc.h>
00026 #endif
00027 
00028 #include "mcs.hh"
00029 using namespace mcs;
00030 
00031 
00032 void printMallinfo(int pos = 0) {
00033 #if HAVE_MALLOC
00034   struct mallinfo mi = mallinfo();
00035   cout << endl << endl << "Dynamic memory (" << pos << "): " << mi.arena << endl << endl;
00036 #else
00037   cout << endl << endl << "No dynamic memory info for this system" << endl;
00038 #endif
00039 }
00040 
00041 
00042 
00043 
00044 string mcs::UserThread::wpath(string fn)
00045 {
00046   string s;
00047 
00048   fn = subst(fn, " "      , ""); // blanks
00049   fn = subst(fn, "\\.\\." , ""); // ..
00050   fn = subst(fn, "\\\\"   , ""); // backslash
00051   fn = subst(fn, "\\\""   , ""); // double quotes
00052   fn = subst(fn, "\\\'"   , ""); // single quotes
00053 
00054   //s = env->path;
00055   s = ".";
00056   if (env->cl_work) {
00057       if (env->cl_work_cid)
00058       s += string("/U") + string(tid());
00059       else
00060       s += string("/") + user;
00061 
00062       s += "/";
00063   }
00064 
00065   return s + fn;
00066 }
00067 
00068 
00069 
00070 RetValue mcs::UserThread::Send(Event e, bool log)
00071 {
00072     sock->print(e.codemsg());
00073     e.lmsg = " >" + e.lmsg;  //Friendness of UserThread to Event class
00074     if (log) Log(e);
00075     return e.type();
00076 }
00077 
00078 
00079 
00080 RetValue mcs::UserThread::Send(Data& data)
00081 {
00082 //    void* buf = NULL;
00083 //    unsigned int size = data.prepareBuffer((void**) &buf);
00084 //    Serializable sss(buf, size);
00085 //  
00086 //    Send(MCS_OK( MSG_SENDDATA_START, 1 )); //1 is for a Data object
00087 //    sock->sendData(&sss);
00088 //    Send(MCS_OK( MSG_DATA_STOP ));
00089 //    free(buf);
00090 //    return OK;
00091 
00092     Send(MCS_OK( MSG_SENDDATA_START, 1 )); //1 is for a Data object
00093     sock->sendData(&data);
00094     Send(MCS_OK( MSG_DATA_STOP ));
00095     return OK;
00096 }
00097 
00098 
00099 RetValue mcs::UserThread::Send(Record& vec)
00100 {
00101 //    void* buf = NULL;
00102 //    unsigned int size = vec.prepareBuffer((void**) &buf);
00103 //    Serializable sss(buf, size);
00104 //
00105 //    Send(MCS_OK( MSG_SENDDATA_START, 2 )); //2 is for a Record object
00106 //    sock->sendData(&sss);
00107 //    Send(MCS_OK( MSG_DATA_STOP ));
00108 //    free(buf);
00109 //    return OK;
00110 
00111     Send(MCS_OK( MSG_SENDDATA_START, 2 )); //2 is for a Record object
00112     sock->sendData(&vec);
00113     Send(MCS_OK( MSG_DATA_STOP ));
00114     return OK;
00115 }
00116 
00117 
00118 RetValue mcs::UserThread::Send(string filename, string path)
00119 {
00120     Send(MCS_OK( MSG_SENDFILE_START, filename.csz ));
00121     Serializable sss(path, env->cl_chunksize);
00122     sock->sendData(&sss);
00123     Send(MCS_OK( MSG_FILE_STOP ));
00124     return OK;
00125 }
00126 
00127 
00128 RetValue mcs::UserThread::Send(vector<string> vec)
00129 {
00130     for (unsigned int ui=0; ui<vec.size(); ui++)
00131     Send(MCS_OK( MSG_OUT, vec[ui].c_str() ), false);
00132 
00133   return OK;
00134 }
00135 
00136 
00137 
00138 #if ENABLE_MYSQL
00139 RetValue mcs::UserThread::sendQueryRes()
00140 {
00141   RetValue ret = OK;
00142 
00143   if (query->gotRecordSet()) {
00144     try {
00145       //printMallinfo(1);
00146       Send(MCS_OK( MSG_SENDFILE_START, "query.out" ));
00147       //printMallinfo(2);
00148       query->Result2Ascii(wpath("query.out"));
00149       //printMallinfo(3);
00150       Serializable file(wpath("query.out"), env->cl_chunksize);
00151       //printMallinfo(4);
00152       sock->sendData(&file);
00153       //printMallinfo(5);
00154     }
00155     catch (Event& e) {
00156     if (e.type() == FATAL) throw;
00157     ret = Send(e);
00158     }
00159     //printMallinfo();
00160     return Send(MCS_( ret, MSG_DATA_STOP )) ;
00161   }
00162   else return Send(MCS_WARN( MSG_NO_RESULT ));
00163 }
00164 #endif
00165 
00166 
00167 
00168 
00169 void mcs::UserThread::prompt(RetValue ret)
00170 {
00171     switch (ret) {
00172     case OK:
00173         sock->print(MCS_PROMPT_OK);      break;
00174     case WARN:
00175         sock->print(MCS_PROMPT_WARN);    break;
00176     case ERROR:
00177         sock->print(MCS_PROMPT_ERROR);   break;
00178     default:
00179         throw MCS_FATAL(MSG_UNEXPECTED);
00180     }
00181 }
00182 
00183 
00184 void mcs::UserThread::run()
00185 {
00186   string cmd;
00187   bool first = true;
00188   RetValue ret = OK;
00189 
00190   set_cancel_state(false);
00191 
00192   for (;;) {
00193     try {
00194       if (first) {
00195     //A message to the user must be sent inside hk_connect
00196     ret=hk_connect();
00197     if (ret != OK) return;
00198     
00199     sock = new Socket(csocket, env->timeout, 1000, env->ssl_ctx);
00200 
00201     linfo.ipaddress() = sock->ipaddress();
00202     linfo.hostname() = sock->hostname();
00203     
00204     Send(MCS_OK( MSG_WELCOME, env->localhost.csz,
00205              env->appname.csz, env->appvers.csz));
00206     first = false;
00207       }
00208       else {
00209     set_cancel_state(true);
00210     cmd = sock->getline();
00211     set_cancel_state(false);
00212     
00213     //Synchronize with wakeUpClient()
00214     syn.enter();
00215     ret = exec(cmd);
00216     syn.leave();
00217 
00218     //printMallinfo();
00219       }
00220       prompt(ret);
00221     }
00222     catch(Event e) {
00223       //Unlock the mutex
00224       while (syn.count())
00225     syn.leave();
00226 
00227       ret = e.type();
00228 
00229       if (e.type() == FATAL) {
00230     //If the client gives a "bye" command a FATAL exception with
00231     //code BYE will be thrown.
00232     if (e.code() == MSG_BYE) {
00233     
00234       hk_disconnect();
00235     
00236       //Wait until the client closes the connection, this is
00237       //necessary to prevent "Address already in use" errors. The
00238       //try..catch block is necessary because getline() will throw
00239       //an error when the socket close.
00240       try {cmd = sock->getline(); } catch(...) {}
00241     }
00242     else {
00243       Log(e);
00244     }
00245     
00246     Log( MCS_OK(MSG_USERTHREAD_TERMINATING) );
00247     return;
00248       }
00249     }
00250   }
00251 }
00252 
00253 
00254 
00255 RetValue mcs::UserThread::sendStrings(string str)
00256 {
00257   return Send(split(str, "\n"));
00258 }
00259 
00260 
00261 void mcs::UserThread::wakeUpClient(Event* e)
00262 {
00263   //syn.enter();
00264   if (state() == MCS_STATE_RUNNING) {
00265     if (e)
00266       Send(*e);
00267     else
00268       Send(MCS_OK( MSG_WAKE_UP) );
00269   }
00270   //syn.leave();
00271 }
00272 
00273 
00274 
00275 #define BEGIN_CMD(A)                             \
00276 if ((!cmd_executed)   &&   (cmd.cmpCmd(A))){     \
00277       cmd_executed=true;                         \
00278 
00279 
00280 #define BEGIN_CMD_LOGIN(A)                       \
00281       BEGIN_CMD(A)                               \
00282       if (! loginok) throw MCS_ERROR(MSG_NOT_LOGIN);
00283 
00284 
00285 #define CMD_HELP(A)                              \
00286       if (cmd.givenOpt(MCS_OPT_HELP)) {          \
00287           sendStrings(A);                        \
00288           goto lbl_cmdexecuted;                  \
00289       }
00290 
00291 
00292 #define END_CMD goto lbl_cmdexecuted; }
00293 
00294 
00295 RetValue mcs::UserThread::exec(string scmd, string _pars)
00296 {
00297   int i;
00298   unsigned int ui;
00299   string fn, s, tmp;
00300   bool cmd_executed=false;
00301   unsigned int size;
00302 
00303   bool opt_sqascii;
00304   bool opt_sqfits ;
00305   bool opt_force  ;
00306   bool opt_werr   ;
00307   static string bl = " ";
00308 
00309   CommandParser cmd;
00310   RetValue ret=OK;
00311   RetValue sub=OK;
00312 
00313   batchlevel++;
00314 
00315   try {
00316 
00317   scmd += " " + _pars;
00318   cmd.parseCmd(scmd);
00319   if (cmd.cmd().empty()) return OK;
00320 
00321   opt_sqascii = cmd.givenOpt(MCS_OPT_SAVEQUERYASCII);
00322   opt_sqfits  = cmd.givenOpt(MCS_OPT_SAVEQUERYFITS);
00323   opt_force   = cmd.givenOpt(MCS_OPT_FORCE);
00324   opt_werr    = cmd.givenOpt(MCS_OPT_ALL_ERRORS);
00325 
00326   if (batchlevel > 0)
00327     Send(MCS_OK( MSG_BATCH_START, batchlevel, cmd.cline().csz ));
00328 
00329   if (cmd.cmpCmd(MCS_CMD_PASSWORD)) {
00330       Log(MCS_OK( MSG_LOG_COMMAND, "*** PASSWORD ***" ));
00331   }
00332   else if (cmd.cmpCmd(MCS_CMD_NOP))  //Don't log NOP commands.
00333     ;
00334   else if (cmd.cmpCmd(MCS_CMD_CLIENT_INFO))
00335     Log(MCS_OK( MSG_LOG_COMMAND, cmd.cline().csz ));
00336   else {
00337     Log(MCS_OK( MSG_LOG_COMMAND, cmd.cline().csz ));
00338     linfo.lastCommand() = cmd.cline().substr(0, linfo.lastCommand().maxLength());
00339     linfo.timeLastCommand().settimenow();
00340     linfo.commandExecuted() = linfo.commandExecuted().ival() + 1;
00341   }
00342 
00343 
00344 
00345 #if ! ENABLE_CFITSIO
00346   if (opt_sqfits) {
00347       ret=Send(MCS_WARN( MSG_FITS_NOT_COMPILED ));
00348       opt_sqfits = false;
00349   }
00350 #endif
00351 
00352 #if ! ENABLE_MYSQL
00353   if ((opt_sqfits)   ||   (opt_sqascii)) {
00354       cmd_exected = true;
00355       throw MCS_ERROR(MSG_MYSQL_DISABLED);
00356   }
00357 #endif
00358 
00359   //Custom user routine
00360   if (! cmd_executed)
00361       sub = hk_exec(&cmd, cmd_executed);
00362   if (sub > ret) ret = sub;
00363 
00364 
00365   //................................................................
00366   BEGIN_CMD(MCS_CMD_NOP);
00367   END_CMD;
00368 
00369 
00370   //................................................................
00371   BEGIN_CMD(MCS_CMD_CID);
00372   CMD_HELP(MCS_CMD_CID_HELP);
00373   Send(MCS_OK( MSG_CLIENT_ID, id(), env->cl_chunksize));
00374   END_CMD;
00375 
00376   //................................................................
00377   BEGIN_CMD(MCS_CMD_CLIENT_INFO);
00378   CMD_HELP(MCS_CMD_CLIENT_INFO_HELP);
00379   setActiveRS(env->server->getAll_ClientInfo(), true);
00380   END_CMD;
00381 
00382 
00383   //................................................................
00384   BEGIN_CMD(MCS_CMD_CLOSECLIENT);
00385   CMD_HELP(MCS_CMD_CLOSECLIENT_HELP);
00386   Send(MCS_OK( MSG_BYE ));
00387   throw MCS_FATAL(MSG_BYE);
00388   END_CMD;
00389 
00390 
00391   //................................................................
00392   BEGIN_CMD(MCS_CMD_USERNAME);
00393   CMD_HELP(MCS_CMD_USERNAME_HELP);
00394   if (cmd.argc() >= 1) {
00395       user=cmd.arg(0).sval();
00396       linfo.username() = user;
00397   }
00398   Send(MCS_OK( MSG_WELCOMEUSER, user.csz ));
00399   END_CMD;
00400 
00401 
00402   //................................................................
00403   BEGIN_CMD(MCS_CMD_PASSWORD);
00404   CMD_HELP(MCS_CMD_PASSWORD_HELP);
00405   if (cmd.argc() >= 1) pass=cmd.arg(0).sval();
00406   Send(MCS_OK( MSG_PASSWORD ));
00407   END_CMD;
00408 
00409 
00410   //................................................................
00411   BEGIN_CMD(MCS_CMD_DBNAME);
00412   CMD_HELP(MCS_CMD_DBNAME_HELP);
00413   if (cmd.argc() >= 1) dbname=cmd.arg(0).sval();
00414   Send(MCS_OK( MSG_DBNAME, dbname.csz ));
00415   END_CMD;
00416 
00417 
00418   //................................................................
00419 #ifdef MCS_HAVE_DBH_CMD
00420   BEGIN_CMD(MCS_CMD_DBHOST);
00421   CMD_HELP(MCS_CMD_DBHOST_HELP);
00422   if (cmd.argc() >= 1) dbhost=cmd.arg(0).sval();
00423   Send(MCS_OK( MSG_DBHOST, dbhost.csz ));
00424   END_CMD;
00425 #endif
00426 
00427 
00428   //................................................................
00429   BEGIN_CMD(MCS_CMD_DBCONNECT);
00430   CMD_HELP(MCS_CMD_DBCONNECT_HELP);
00431   if (loginok) throw MCS_WARN(MSG_ALREADY_CONNECTED);
00432 
00433   if (env->cl_custom_auth) {
00434       ret = hk_auth(grants, loginok);
00435       if (ret == OK)
00436       Send(MCS_OK( MSG_CONNECTED, " " ));
00437   }
00438   else {
00439 #if ENABLE_MYSQL
00440       //Check for the presence of values
00441       if      (user.empty()  ) throw MCS_ERROR(MSG_MISSING_FIELD, "username");
00442       else if (pass.empty()  ) throw MCS_ERROR(MSG_MISSING_FIELD, "password");
00443       else if (dbname.empty()) throw MCS_ERROR(MSG_MISSING_FIELD, "db name" );
00444       else if (dbhost.empty()) throw MCS_ERROR(MSG_MISSING_FIELD, "db host" );
00445       else {
00446       db.connect(user, pass, dbname, dbhost);
00447       query = new Query(&db, false);
00448       if (env->cl_read_grants) {
00449           query->query("select grants from users where username='"
00450                + user + "'", true);
00451           if (query->gotRecordSet() && query->nRows() == 1 ) {
00452           grants = query->rec()[0].ival();
00453           Log(MCS_OK( MSG_USER_HAS_GRANTS, user.csz, grants ));
00454           }
00455           else
00456           throw MCS_FATAL(MSG_GRANTS_CANTGET_GRANTS);
00457       }
00458       else
00459           grants=MCS_GRANT_ALL;
00460       }
00461 #else
00462       grants = MCS_GRANT_ALL;
00463 #endif
00464 
00465       if (! (grants & MCS_GRANT_LOGIN))
00466       throw MCS_ERROR(MSG_GRANTS_LOGIN);
00467       else {
00468       loginok=true;
00469       Send(MCS_OK( MSG_CONNECTED, dbname.csz ));
00470       }
00471   }
00472 
00473   linfo.logged() = loginok;
00474 
00475   if (env->cl_work) {
00476     unsigned int size;
00477     if (! File_Dir_Exist(wpath(), size))
00478       mkDir(wpath(), MCS_MKDIR_PROTECT);
00479   }
00480 
00481   if (env->cl_autoexec)
00482       sub=exec(MCS_CMD_EXEC, "auto");
00483   END_CMD;
00484 
00485 
00486   //................................................................
00487 //  BEGIN_CMD_LOGIN(MCS_CMD_CLOSE_DB_CONN);
00488 //#if ENABLE_MYSQL
00489 //  db.close();
00490 //#endif
00491 //  Send(MCS_OK( MSG_CLOSE_DB_CONN ));
00492 //  loginok=false;
00493 //  END_CMD;
00494 
00495 
00496 #if ENABLE_MYSQL
00497   //................................................................
00498   BEGIN_CMD_LOGIN(MCS_CMD_QUERY);
00499   CMD_HELP(MCS_CMD_QUERY_HELP);
00500   if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00501   if (! (grants & MCS_GRANT_QUERY)) throw MCS_ERROR(MSG_GRANTS_QUERY);
00502 
00503   s=cmd.allargs();
00504   query->query(s, true);
00505 
00506   if (query->gotRecordSet()) {
00507       Send(MCS_OK( MSG_DB_QRY_OK ));
00508       setActiveRS(query, false);
00509 
00510       if (opt_sqfits) {
00511 #if ENABLE_CFITSIO
00512     //query->Result2Fits(wpath(fnout));
00513 #endif
00514     opt_sqfits=false;
00515       }
00516       else if (opt_sqascii) {
00517       query->Result2Ascii(wpath(fnout));
00518       opt_sqascii=false;
00519       }
00520   }
00521   else
00522       Send(MCS_OK( MSG_DB_ROWSAFF, query->nAffectedRows() ));
00523   END_CMD;
00524 
00525 
00527   //BEGIN_CMD_LOGIN(MCS_CMD_ROWS);
00528   //CMD_HELP(MCS_CMD_ROWS_HELP);
00529   //if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00530   //if (! query->gotRecordSet()) throw MCS_WARN(MSG_NO_RESULT);
00531   //
00532   //if (query->gotRecordSet())
00533   //    Send(MCS_OK( MSG_DB_ROWSAFF, query->nRows() ));
00534   //END_CMD;
00535 
00536 
00538   //BEGIN_CMD_LOGIN(MCS_CMD_FIELDS);
00539   //CMD_HELP(MCS_CMD_FIELDS_HELP);
00540   //if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00541   //if (! query->gotRecordSet()) throw MCS_WARN(MSG_NO_RESULT);
00542   //
00543   //Send( query->ExecutionDetails() );
00544   //END_CMD;
00545 
00546 
00547   //................................................................
00548   BEGIN_CMD_LOGIN(MCS_CMD_SENDQUERYRES);
00549   CMD_HELP(MCS_CMD_SENDQUERYRES_HELP);
00550   if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00551   if (! (grants & MCS_GRANT_GET)) throw MCS_ERROR(MSG_GRANTS_GET);
00552   if (! query->gotRecordSet()) throw MCS_WARN(MSG_NO_RESULT);
00553 
00554   sub=sendQueryRes();
00555   END_CMD;
00556 
00557 
00558   //................................................................
00559   BEGIN_CMD_LOGIN(MCS_CMD_RECORD);
00560   CMD_HELP(MCS_CMD_RECORD_HELP);
00561   if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00562   if (! (grants & MCS_GRANT_GET)) throw MCS_ERROR(MSG_GRANTS_GET);
00563   if (! rs) throw MCS_WARN(MSG_NO_RESULT);
00564 
00565   unsigned int pos = cmd.arg(0).ival();
00566   if (pos == rs->pos())
00567     Send(rs->rec());
00568   else if (pos == rs->pos()+1) {
00569     if (rs->setNext())
00570       Send(rs->rec());
00571     else
00572       Send( MCS_OK(MSG_FETCH_EOF) );
00573   }
00574   else {
00575     rs->setPos(pos);
00576     Send(rs->rec());
00577   }
00578   END_CMD;
00579 
00580 
00581   //................................................................
00582   BEGIN_CMD_LOGIN(MCS_CMD_TABLELIST);
00583   CMD_HELP(MCS_CMD_TABLELIST_HELP);
00584   if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00585 
00586   s = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '"
00587     + dbname + "' AND TABLE_TYPE = 'BASE TABLE'";
00588   exec(MCS_CMD_QUERY + bl + s);
00589   //query->readTableList();
00590   //Send( query->tableList );
00591   END_CMD;
00592 
00593 
00594   //................................................................
00595   BEGIN_CMD_LOGIN(MCS_CMD_TABLEINFO);
00596   CMD_HELP(MCS_CMD_TABLEINFO_HELP);
00597   if (! env->cl_have_db) throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
00598   if ((cmd.argc() < 1)   ||   (cmd.arg(0).sval().empty()))
00599       throw MCS_WARN(MSG_MISSING_FIELD, "table name");
00600 
00601   s = "SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '"
00602     + dbname + "' AND TABLE_NAME = '" + cmd.arg(0).sval() + "'";
00603 
00604   exec(MCS_CMD_QUERY + bl + s);
00605   //exec(MCS_CMD_QUERY + bl + "DESCRIBE " + cmd.arg(0).sval());
00606   //Send( query->tableInfo(cmd.arg(0).sval()) );
00607   END_CMD;
00608 
00609 #endif  //ENABLE_MYSQL
00610 
00611 
00612 
00613   //................................................................
00614   BEGIN_CMD_LOGIN(MCS_CMD_EXEC);
00615   CMD_HELP(MCS_CMD_EXEC_HELP);
00616   if (! (grants & MCS_GRANT_SCRIPTS)) throw MCS_ERROR(MSG_GRANTS_SCRIPT);
00617 
00618   s = fn = cmd.arg(0).sval();
00619   i = chkExt(fn);
00620 
00621   if ((i == MCS_FT_BIN)   ||   (i == MCS_FT_SCRIPT)) {
00622 #if ENABLE_DEBUG
00623     tmp = fn + " " + cmd.line_afterToken(1);
00624     Log(MCS_OK( MSG_SCRIPT_START, tmp.csz ));
00625 #endif
00626     Send(MCS_OK( MSG_SCRIPT_START, s.csz ));
00627 
00628     i = spawn(fn, cmd.line_afterToken(1),
00629           wpath(), itos(id()),
00630           user, pass, dbname,
00631           wpath(fnout), wpath(fnerr));
00632     if (i != 0)
00633       throw MCS_WARN(MSG_SCRIPT_ERROR, i);
00634 
00635     Send(MCS_OK( MSG_SCRIPT_STOP, s.csz ));
00636   }
00637   else {
00638     string c="";
00639     bool had_warn = false;
00640     bool had_err  = false;
00641     bool stop = false;
00642     vector<string> vec = cmd.replPars_onFile(fn);
00643     if (i == MCS_FT_BATCH)
00644       Send(MCS_OK( MSG_BATCH_START, batchlevel,  s.csz ));
00645     if (i == MCS_FT_SQL)  {
00646 #if ENABLE_MYSQL
00647       Send(MCS_OK( MSG_SQL_START, s.csz )); c = MCS_CMD_QUERY;
00648 #else
00649       throw MCS_ERROR(MSG_DB_NOT_COMPILED);
00650 #endif
00651     }
00652 
00653     for (ui=0; ui<vec.size(); ui++) {
00654 
00655       sub=exec(c.csz, vec[ui]);
00656 
00657       switch(sub) {
00658       case OK:
00659     break;
00660       case WARN:
00661     had_warn = true;
00662     if (opt_werr) stop = true;
00663     break;
00664       case ERROR:
00665     had_err  = true;
00666     if (! opt_force) stop = true;
00667     break;
00668       case FATAL:
00669     throw MCS_FATAL(MSG_UNEXPECTED);
00670     break;  //Is unexpected because an exception should be thrown
00671       }
00672 
00673       if (stop) break;
00674     }
00675 
00676     if (had_err)       ret = ERROR;
00677     else if (had_warn) ret = WARN;
00678     else               ret = OK;
00679 
00680     if (i == MCS_FT_BATCH)  Send(MCS_OK( MSG_BATCH_STOP, batchlevel ));
00681     if (i == MCS_FT_SQL) {
00682       Send(MCS_OK( MSG_SQL_STOP ));
00683 
00684       if ((ret == OK)   &&   query->gotRecordSet()) {
00685     if (opt_sqfits) {
00686 #if ENABLE_CFITSIO
00687       //query->Result2Fits(wpath(fnout));
00688 #endif
00689       opt_sqfits=false;
00690     }
00691     else if (opt_sqascii) {
00692       query->Result2Ascii(wpath(fnout));
00693       opt_sqascii=false;
00694     }
00695       }
00696     }
00697   }
00698   END_CMD;
00699 
00700 
00701   //................................................................
00702   BEGIN_CMD_LOGIN(MCS_CMD_GET);
00703   CMD_HELP(MCS_CMD_GET_HELP);
00704   if (! (grants & MCS_GRANT_GET)) throw MCS_ERROR(MSG_GRANTS_GET);
00705 
00706   fn = wpath(fnout);
00707   s  = fnout;
00708   if (cmd.argc() == 1) {
00709       fn = wpath(cmd.arg(0).sval());
00710       s  = cmd.arg(0).sval();
00711   }
00712 
00713   ret = Send(s, fn);
00714   END_CMD;
00715 
00716 
00717 
00718 //This has been commented because data in the "send" vector are automatically
00719 //sent after each command.
00720 //  //................................................................
00721 //  BEGIN_CMD_LOGIN(MCS_CMD_GETDATA);
00722 //  CMD_HELP(MCS_CMD_GETDATA_HELP);
00723 //  if (! (grants & MCS_GRANT_GET)) throw MCS_ERROR(MSG_GRANTS_GET);
00724 //  if (cmd.argc() < 1) throw MCS_ERROR(MSG_MISSING_FIELD, "object index");
00725 //
00726 //  ui = cmd.arg(0).ival();
00727 //  if (ui < send.count()) {
00728 //      tbuf = NULL;
00729 //      size = send.pop(ui).prepareBuffer((void**) &tbuf);
00730 //      Serializable sss(tbuf, size);
00731 //
00732 //      Send(MCS_OK( MSG_SENDDATA_START, 1 )); //1 is for a Data object
00733 //      sock->sendData(&sss);
00734 //      Send(MCS_OK( MSG_DATA_STOP ));
00735 //      free(tbuf);
00736 //  }
00737 //  else
00738 //      throw MCS_ERROR(MSG_INDEX_OUT_RANGE, ui, send.count());
00739 //  END_CMD;
00740 
00741 
00742   //................................................................
00743   BEGIN_CMD_LOGIN(MCS_CMD_PUT);
00744   CMD_HELP(MCS_CMD_PUT_HELP);
00745   if (! (grants & MCS_GRANT_PUT)) throw MCS_ERROR(MSG_GRANTS_PUT);
00746   if (cmd.argc() < 1) throw MCS_ERROR(MSG_MISSING_FIELD, "file name, size");
00747 
00748   s  = cmd.arg(0).sval();
00749   if (strchr(s.c_str(), '/')) {  //A path is specified
00750     if (s[0] == '/')
00751       throw MCS_ERROR( MSG_NO_ABSOLUTE_PATH, s );
00752 
00753     if (strstr(s.c_str(), ".."))
00754       throw MCS_ERROR( MSG_NO_DOUBLEDOT_PATH, s );
00755 
00756     string subdir = wpath(s);
00757     int loc = subdir.rfind('/');
00758     subdir.resize(loc);
00759     unsigned int size;
00760     if (! File_Dir_Exist(subdir, size))
00761       mkDir(subdir, MCS_MKDIR_PROTECT);
00762   }
00763   fn = wpath(s);
00764   size = cmd.arg(1).ulval();
00765 
00766   Send(MCS_OK( MSG_RECVFILE_START, s.csz ));
00767   sock->recvData(fn);
00768   ret = Send(MCS_OK( MSG_FILE_STOP, s.csz ));
00769   END_CMD;
00770 
00771 
00772   //................................................................
00773   BEGIN_CMD_LOGIN(MCS_CMD_PUTDATA);
00774   CMD_HELP(MCS_CMD_PUTDATA_HELP);
00775   if (! (grants & MCS_GRANT_PUT)) throw MCS_ERROR(MSG_GRANTS_PUT);
00776   if (cmd.argc() < 1) throw MCS_ERROR(MSG_MISSING_FIELD, "size");
00777 
00778   size = cmd.arg(0).ulval();
00779   Send(MCS_OK( MSG_RECVDATA_START ));
00780   char* tbuf = NULL;
00781   size = sock->recvData(&tbuf, 0);
00782 
00783   Data d(tbuf);
00784   d.setSourceID(MCS_ID_CLIENT);
00785   d.setDestID(userID());
00786   recv.addField(d);
00787 
00788   Send(MCS_OK( MSG_DATA_STOP ));
00789 
00790   if (cmd.givenOpt(MCS_OPT_LOOP)) {
00791       Send(MCS_OK( MSG_COPYING_DATA_OBJECTS, "send Record" ));
00792       send.addField(d);
00793   }
00794 
00795   free(tbuf);
00796   END_CMD;
00797 
00798 
00799   //................................................................
00800   if (! cmd_executed)
00801       throw MCS_ERROR(MSG_SYNTAX, cmd.cline().csz);
00802 
00803 
00804   lbl_cmdexecuted:
00805   ; //Continue from here if the command has been excuted
00806 
00807 
00808 //Eventually send objects in the send Record
00809   if (ret == OK)
00810       while (send.count()) {
00811       Data d = send.pop();
00812       Send(d);
00813       }
00814 
00815   hk_postexec(&cmd, ret);
00816 
00817   if (batchlevel > 0)
00818       Send(MCS_OK( MSG_BATCH_STOP, batchlevel ));
00819 
00820 
00821   }   // try
00822   catch(Event e) {
00823       if (e.type() != FATAL)
00824       ret = Send(e);
00825       else
00826       throw e;
00827   }
00828 
00829   batchlevel--;
00830   return ret;
00831 }
00832 
00833 
00834 
00835 mcs::UserThread::UserThread(Thread* parent, int lID, int newsock) :
00836   BaseThread(parent, lID),
00837   syn(),
00838   recv(true)
00839 {
00840   Log(MCS_OK( MSG_THREAD_CREATE, "UserThread" ));
00841   //printMallinfo();
00842 
00843   sock = NULL;
00844 
00845   syn.synchronize(true);
00846 
00847   csocket = 0;
00848   if (newsock) {
00849     csocket = newsock;
00850   }
00851 
00852   loginok=false;
00853   grants=0;
00854   batchlevel=-1;
00855 
00856   fnout="out";
00857   fnerr="err";
00858 
00859   dbhost="localhost";
00860   dbname=env->appname;
00861 
00862   linfo.id() = lID;
00863   linfo.timeConnetcted().settimenow();
00864 
00865   luserid = MCS_ID_UNKNOWN;
00866 
00867 #if ENABLE_MYSQL
00868   if (env->cl_have_db)
00869       query = NULL;
00870 #endif
00871 
00872   rs = NULL;
00873 }
00874 
00875 
00876 void mcs::UserThread::setActiveRS(RecordSet* rs, bool delWhenFinished)
00877 {
00878   if ( (this->rs)   &&   (deleters) )
00879     delete this->rs;
00880 
00881   this->rs = rs;
00882   deleters = delWhenFinished;
00883 
00884   Record* tmp = rs->prepRecToSend();
00885 
00886   Send(*tmp);
00887   delete tmp;
00888   Send( MCS_OK( MSG_NEW_RECORDSET ) );
00889 }
00890 
00891 
00892 mcs::UserThread::~UserThread()
00893 {
00894   if ( (this->rs)   &&   (deleters) )
00895     delete rs;
00896 
00897   if (env->cl_work   &&   env->cl_clean_logout)
00898     rmDir(wpath());
00899 
00900   if (sock) {
00901     delete sock;
00902     sock = NULL;
00903   }
00904 
00905 #if ENABLE_MYSQL
00906   if (env->cl_have_db)
00907     try { if (query) delete query;  }
00908     catch (Event &e) {}
00909 #endif
00910 
00911   //printMallinfo();
00912 
00913   Log(MCS_OK( MSG_THREAD_DESTROY, "UserThread" ));
00914 }
00915 
00916 
00917 
00918 ClientInfo& mcs::UserThread::info()
00919 {
00920   return linfo;
00921 }
00922 
00923 
00924 
00925 RetValue mcs::UserThread::hk_exec(CommandParser* cmd, bool& cmd_executed)
00926 {
00927     RetValue ret = OK;
00928     cmd_executed = false;
00929 
00930     if (env->server->cb_exec)
00931     ret = (*(env->server->cb_exec))(cmd, cmd_executed);
00932 
00933     if (env->server->cbwa_exec)
00934     (*(env->server->cbwa_exec))();
00935 
00936     return ret;
00937 }
00938 
00939 void mcs::UserThread::hk_postexec(CommandParser* cmd, RetValue ret)
00940 {
00941     if (env->server->cb_postexec)
00942     (*(env->server->cb_postexec))(cmd, ret);
00943 
00944     if (env->server->cbwa_postexec)
00945     (*(env->server->cbwa_postexec))();
00946 }
00947 
00948 RetValue mcs::UserThread::hk_connect()
00949 {
00950     RetValue ret = OK;
00951 
00952     if (env->server->cb_connect)
00953     ret = (*(env->server->cb_connect))();
00954 
00955     if (env->server->cbwa_connect)
00956     (*(env->server->cbwa_connect))();
00957 
00958   return ret;
00959 }
00960 
00961 void mcs::UserThread::hk_disconnect()
00962 {
00963     if (env->server->cb_disconnect)
00964         (*(env->server->cb_disconnect))();
00965 }
00966 
00967 
00968 RetValue mcs::UserThread::hk_auth(int& grants, bool& loginok)
00969 {
00970     RetValue ret = OK;
00971     grants = MCS_GRANT_ALL;
00972     loginok = true;
00973 
00974     if (env->server->cb_auth)
00975     ret = (*(env->server->cb_auth))(grants, loginok);
00976 
00977     if (env->server->cbwa_auth)
00978     (*(env->server->cbwa_auth))();
00979 
00980     return ret;
00981 }
00982 
00983 
00984 Server* mcs::UserThread::parent()
00985 {
00986   return env->server;
00987 }
00988 
00989 
00990 string mcs::UserThread::userName()
00991 {
00992   string ret;
00993   ret = user;
00994   return ret;
00995 }
00996 
00997 
00998 
00999 int mcs::UserThread::userID()
01000 {
01001   return luserid;
01002 }
01003 
01004 
01005 void mcs::UserThread::send2OtherThread(Data& d, int dest)
01006 {
01007   d.setSourceID(userID());
01008   d.setDestID(dest);
01009   env->server->dispatch.addField(d);
01010 }
01011 

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha3
Documentation generated on Thu Mar 22 13:22:23 UTC 2012