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
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|