41 void printMallinfo(
int pos = 0) {
46 cout <<
"\n\nDynamic memory (" << pos <<
"): " << mi.arena << endl << endl;
48 cout << setw(10)<< mi.arena <<
" int arena; /* non-mmapped space allocated from system */\n" 49 << setw(10)<< mi.ordblks <<
" int ordblks; /* number of free chunks */\n" 50 << setw(10)<< mi.smblks <<
" int smblks; /* number of fastbin blocks */\n" 51 << setw(10)<< mi.hblks <<
" int hblks; /* number of mmapped regions */\n" 52 << setw(10)<< mi.hblkhd <<
" int hblkhd; /* space in mmapped regions */\n" 53 << setw(10)<< mi.usmblks <<
" int usmblks; /* maximum total allocated space */\n" 54 << setw(10)<< mi.fsmblks <<
" int fsmblks; /* space available in freed fastbin blocks */\n" 55 << setw(10)<< mi.uordblks <<
" int uordblks; /* total allocated space */\n" 56 << setw(10)<< mi.fordblks <<
" int fordblks; /* total free space */\n" 57 << setw(10)<< mi.keepcost <<
" int keepcost; /* top-most, releasable (via malloc_trim) space */\n\n";
59 cout <<
"\n\nNo dynamic memory info for this system.\n";
69 fn =
subst(fn,
" " ,
"");
70 fn =
subst(fn,
"\\.\\." ,
"");
71 fn =
subst(fn,
"\\\\" ,
"");
72 fn =
subst(fn,
"\\\"" ,
"");
73 fn =
subst(fn,
"\\\'" ,
"");
79 s += string(
"/U") + string(tid());
81 s += string(
"/") + user;
113 Send(
MCS_OK( MSG_SENDDATA_START, 1 ));
114 sock->sendData(&data);
115 Send(
MCS_OK( MSG_DATA_STOP ));
132 Send(
MCS_OK( MSG_SENDDATA_START, 2 ));
133 sock->sendData(&vec);
134 Send(
MCS_OK( MSG_DATA_STOP ));
141 Send(
MCS_OK( MSG_SENDFILE_START, filename.csz ));
143 sock->sendData(&sss);
144 Send(
MCS_OK( MSG_FILE_STOP ));
151 for (
unsigned int ui=0; ui<vec.size(); ui++)
152 Send(
MCS_OK( MSG_OUT, vec[ui].c_str() ),
false);
164 if (query->gotRecordSet()) {
167 Send(
MCS_OK( MSG_SENDFILE_START,
"query.out" ));
169 query->Result2Ascii(wpath(
"query.out"));
171 Serializable file(wpath(
"query.out"), env->cl_chunksize);
173 sock->sendData(&file);
181 return Send(
MCS_( ret, MSG_DATA_STOP )) ;
183 else return Send(
MCS_WARN( MSG_NO_RESULT ));
211 set_cancel_state(
false);
218 if (ret !=
OK)
return;
220 sock =
new Socket(csocket, env->timeout, 1000, env->ssl_ctx);
222 linfo.ipaddress() = sock->ipaddress();
223 linfo.hostname() = sock->hostname();
225 Send(
MCS_OK( MSG_WELCOME, env->localhost.csz,
226 env->appname.csz, env->appvers.csz));
230 set_cancel_state(
true);
231 cmd = sock->getline();
232 set_cancel_state(
false);
253 if (e.
code() == MSG_BYE) {
261 try {cmd = sock->getline(); }
catch(...) {}
267 Log(
MCS_OK(MSG_USERTHREAD_TERMINATING) );
278 return Send(
split(str,
"\n"));
289 Send(
MCS_OK( MSG_WAKE_UP) );
296 #define BEGIN_CMD(A) \ 297 if ((!cmd_executed) && (cmd.cmpCmd(A))){ \ 301 #define BEGIN_CMD_LOGIN(A) \ 303 if (! loginok) throw MCS_ERROR(MSG_NOT_LOGIN); 306 #define CMD_HELP(A) \ 307 if (cmd.givenOpt(MCS_OPT_HELP)) { \ 309 goto lbl_cmdexecuted; \ 313 #define END_CMD goto lbl_cmdexecuted; } 321 bool cmd_executed=
false;
328 static string bl =
" ";
340 if (cmd.
cmd().empty())
return OK;
348 Send(
MCS_OK( MSG_BATCH_START, batchlevel, cmd.
cline().csz ));
351 Log(
MCS_OK( MSG_LOG_COMMAND,
"*** PASSWORD ***" ));
359 linfo.lastCommand() = cmd.
cline().substr(0, linfo.lastCommand().maxLength());
360 linfo.timeLastCommand().settimenow();
361 linfo.commandExecuted() = linfo.commandExecuted().ival() + 1;
368 ret=Send(
MCS_WARN( MSG_FITS_NOT_COMPILED ));
374 if ((opt_sqfits) || (opt_sqascii)) {
382 sub = hk_exec(&cmd, cmd_executed);
383 if (sub > ret) ret = sub;
393 CMD_HELP(MCS_CMD_CID_HELP);
394 Send(
MCS_OK( MSG_CLIENT_ID,
id(), env->cl_chunksize));
399 CMD_HELP(MCS_CMD_CLIENT_INFO_HELP);
400 setActiveRS(env->server->getAll_ClientInfo(),
true);
406 CMD_HELP(MCS_CMD_CLOSECLIENT_HELP);
414 CMD_HELP(MCS_CMD_USERNAME_HELP);
415 if (cmd.
argc() >= 1) {
417 linfo.username() = user;
419 Send(
MCS_OK( MSG_WELCOMEUSER, user.csz ));
425 CMD_HELP(MCS_CMD_PASSWORD_HELP);
427 Send(
MCS_OK( MSG_PASSWORD ));
433 CMD_HELP(MCS_CMD_DBNAME_HELP);
435 Send(
MCS_OK( MSG_DBNAME, dbname.csz ));
440 #ifdef MCS_HAVE_DBH_CMD 441 BEGIN_CMD(MCS_CMD_DBHOST);
442 CMD_HELP(MCS_CMD_DBHOST_HELP);
444 Send(
MCS_OK( MSG_DBHOST, dbhost.csz ));
451 CMD_HELP(MCS_CMD_DBCONNECT_HELP);
452 if (loginok)
throw MCS_WARN(MSG_ALREADY_CONNECTED);
454 if (env->cl_custom_auth) {
455 ret = hk_auth(grants, loginok);
457 Send(
MCS_OK( MSG_CONNECTED,
" " ));
462 if (user.empty() )
throw MCS_ERROR(MSG_MISSING_FIELD,
"username");
463 else if (pass.empty() )
throw MCS_ERROR(MSG_MISSING_FIELD,
"password");
464 else if (dbname.empty())
throw MCS_ERROR(MSG_MISSING_FIELD,
"db name" );
465 else if (dbhost.empty())
throw MCS_ERROR(MSG_MISSING_FIELD,
"db host" );
467 db.connect(user, pass, dbname, dbhost);
468 query =
new Query(&db,
false);
469 if (env->cl_read_grants) {
470 query->query(
"select grants from users where username='" 472 if (query->gotRecordSet() && query->nRows() == 1 ) {
473 grants = query->rec()[0].ival();
474 Log(
MCS_OK( MSG_USER_HAS_GRANTS, user.csz, grants ));
477 throw MCS_FATAL(MSG_GRANTS_CANTGET_GRANTS);
480 grants=MCS_GRANT_ALL;
483 grants = MCS_GRANT_ALL;
486 if (! (grants & MCS_GRANT_LOGIN))
490 Send(
MCS_OK( MSG_CONNECTED, dbname.csz ));
494 linfo.logged() = loginok;
499 mkDir(wpath(), MCS_MKDIR_PROTECT);
502 if (env->cl_autoexec)
520 CMD_HELP(MCS_CMD_QUERY_HELP);
521 if (! env->cl_have_db)
throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
522 if (! (grants & MCS_GRANT_QUERY))
throw MCS_ERROR(MSG_GRANTS_QUERY);
525 query->query(s,
true);
527 if (query->gotRecordSet()) {
528 Send(
MCS_OK( MSG_DB_QRY_OK ));
529 setActiveRS(query,
false);
537 else if (opt_sqascii) {
538 query->Result2Ascii(wpath(fnout));
543 Send(
MCS_OK( MSG_DB_ROWSAFF, query->nAffectedRows() ));
570 CMD_HELP(MCS_CMD_SENDQUERYRES_HELP);
571 if (! env->cl_have_db)
throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
572 if (! (grants & MCS_GRANT_GET))
throw MCS_ERROR(MSG_GRANTS_GET);
573 if (! query->gotRecordSet())
throw MCS_WARN(MSG_NO_RESULT);
581 CMD_HELP(MCS_CMD_RECORD_HELP);
582 if (! env->cl_have_db)
throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
583 if (! (grants & MCS_GRANT_GET))
throw MCS_ERROR(MSG_GRANTS_GET);
584 if (! rs)
throw MCS_WARN(MSG_NO_RESULT);
586 unsigned int pos = cmd.
arg(0).
ival();
587 if (pos == rs->pos())
589 else if (pos == rs->pos()+1) {
593 Send(
MCS_OK(MSG_FETCH_EOF) );
604 CMD_HELP(MCS_CMD_TABLELIST_HELP);
605 if (! env->cl_have_db)
throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
607 s =
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '" 608 + dbname +
"' AND TABLE_TYPE = 'BASE TABLE'";
617 CMD_HELP(MCS_CMD_TABLEINFO_HELP);
618 if (! env->cl_have_db)
throw MCS_ERROR(MSG_DB_ERR_NOTACTIVATED);
619 if ((cmd.
argc() < 1) || (cmd.
arg(0).
sval().empty()))
620 throw MCS_WARN(MSG_MISSING_FIELD,
"table name");
622 s =
"SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" 623 + dbname +
"' AND TABLE_NAME = '" + cmd.
arg(0).
sval() +
"'";
630 #endif //ENABLE_MYSQL 636 CMD_HELP(MCS_CMD_EXEC_HELP);
637 if (! (grants & MCS_GRANT_SCRIPTS))
throw MCS_ERROR(MSG_GRANTS_SCRIPT);
645 Log(
MCS_OK( MSG_SCRIPT_START, tmp.csz ));
647 Send(
MCS_OK( MSG_SCRIPT_START, s.csz ));
652 wpath(fnout), wpath(fnerr));
654 throw MCS_WARN(MSG_SCRIPT_ERROR, i);
656 Send(
MCS_OK( MSG_SCRIPT_STOP, s.csz ));
660 bool had_warn =
false;
661 bool had_err =
false;
665 Send(
MCS_OK( MSG_BATCH_START, batchlevel, s.csz ));
674 for (ui=0; ui<vec.size(); ui++) {
676 sub=exec(c.csz, vec[ui]);
683 if (opt_werr) stop =
true;
687 if (! opt_force) stop =
true;
697 if (had_err) ret =
ERROR;
698 else if (had_warn) ret =
WARN;
703 Send(
MCS_OK( MSG_SQL_STOP ));
705 if ((ret ==
OK) && query->gotRecordSet()) {
712 else if (opt_sqascii) {
713 query->Result2Ascii(wpath(fnout));
724 CMD_HELP(MCS_CMD_GET_HELP);
725 if (! (grants & MCS_GRANT_GET))
throw MCS_ERROR(MSG_GRANTS_GET);
729 if (cmd.
argc() == 1) {
765 CMD_HELP(MCS_CMD_PUT_HELP);
766 if (! (grants & MCS_GRANT_PUT))
throw MCS_ERROR(MSG_GRANTS_PUT);
767 if (cmd.
argc() < 1)
throw MCS_ERROR(MSG_MISSING_FIELD,
"file name, size");
770 if (strchr(s.c_str(),
'/')) {
772 throw MCS_ERROR( MSG_NO_ABSOLUTE_PATH, s );
774 if (strstr(s.c_str(),
".."))
775 throw MCS_ERROR( MSG_NO_DOUBLEDOT_PATH, s );
777 string subdir = wpath(s);
778 unsigned int ui = subdir.rfind(
'/');
781 mkDir(subdir, MCS_MKDIR_PROTECT);
786 Send(
MCS_OK( MSG_RECVFILE_START, s.csz ));
788 ret = Send(
MCS_OK( MSG_FILE_STOP, s.csz ));
794 CMD_HELP(MCS_CMD_PUTDATA_HELP);
795 if (! (grants & MCS_GRANT_PUT))
throw MCS_ERROR(MSG_GRANTS_PUT);
796 if (cmd.
argc() < 1)
throw MCS_ERROR(MSG_MISSING_FIELD,
"size");
799 Send(
MCS_OK( MSG_RECVDATA_START ));
801 size = sock->recvData(&tbuf, 0);
804 d.setSourceID(MCS_ID_CLIENT);
805 d.setDestID(userID());
808 Send(
MCS_OK( MSG_DATA_STOP ));
811 Send(
MCS_OK( MSG_COPYING_DATA_OBJECTS,
"send Record" ));
830 while (send.count()) {
835 hk_postexec(&cmd, ret);
838 Send(
MCS_OK( MSG_BATCH_STOP, batchlevel ));
860 Log(
MCS_OK( MSG_THREAD_CREATE,
"UserThread" ));
896 void mcs::UserThread::setActiveRS(
RecordSet* rs,
bool delWhenFinished)
898 if ( (this->rs) && (deleters) )
902 deleters = delWhenFinished;
904 Record* tmp = rs->prepRecToSend();
914 if ( (this->rs) && (deleters) )
933 Log(
MCS_OK( MSG_THREAD_DESTROY,
"UserThread" ));
948 cmd_executed =
false;
951 ret = (*(
env->server->
cb_exec))(cmd, cmd_executed);
991 grants = MCS_GRANT_ALL;
1019 int mcs::UserThread::userID()
1027 d.setSourceID(userID());
#define MCS_CMD_CLIENT_INFO
Command: Return server status information.
string wpath(string fn="")
Return the path of the work directory followed by the path given in parameter.
void run()
The body of the thread.
#define MCS_FT_SQL
Return value for BaseThread.fileType(), SQL file.
RetValue Log(Event e)
Logging facility.
string itos(int i)
Convert an integer to a string.
void settimenow()
Convert current time value to base type and store in internal buffer.
string cline()
Returns the entire command line.
unsigned long long int ulval() const
Convert internal data to an unsigned long long integer value.
int luserid
The userid of current user.
Serialize memory buffers or files into chunks.
Base class for MCS threaded objects.
string allargs()
Returns all arguments (not tokens!) as a string.
void(* cbwa_postexec)()
Pointer to a void callback function without arguments, called by hk_postexec().
string fnout
Default output file.
Execute queries on the database.
void parseCmd(string c)
Parse a command line into tokens, arguments and options.
bool File_Dir_Exist(string fn, unsigned int &size)
Check if a file or directory exists.
vector< string > replPars_onFile(string fn)
Parse a MCS script.
void(* cbwa_exec)()
Pointer to a void callback function without arguments, called by hk_exec().
string sval(bool addWhiteSpaces=false) const
Convert internal data to a string object.
#define MCS_CMD_GET
Command: Download a file from the work directory.
int batchlevel
Nested batch level.
Class holding information about a client connection.
Main server class for a MCS-based application.
void synchronize(bool setactive)
Enable or disable the synchronization feature.
#define MCS_OPT_SAVEQUERYASCII
Option: Save query result in ASCII format.
Record dispatch
Record of Data objects to be sent to various threads.
Hold informations about an event.
static Env * env
Pointer to the actual Env object, this can be seen in all threaded object.
A dynamic array of Data objects.
#define MCS_CMD_SENDQUERYRES
Command: Retrieve a file with an ASCII dump of the entire set of records returned by the last query...
bool loginok
Tells if client has logged in correctly.
RetValue sendStrings(string str)
Send strings to client.
virtual RetValue hk_connect()
Virtual method called when a new user connects to the server.
#define MCS_OPT_LOOP
Option: Put a copy of thr recevied Data object in the "send" vector.
string fnerr
Default error file.
string dbhost
Host running database server.
#define MCS_(TYPE, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
int csocket
C socket descriptor, used to initialize the Socket object.
void send2OtherThread(Data &d, int destid)
Used to send data object to other threads.
string line_afterToken(int i)
Return the "rest" relative to token at i-th position.
The base class that implement the data abstraction layer.
#define MCS_ERROR(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
string codemsg()
Return the code and the message, formatted as MCS_PRE CODE MESSAGE.
Server * parent()
Return the address of the Server object which generates this Thread.
#define MCS_CMD_PUTDATA
Command: Upload Data objects.
#define MCS_FT_BATCH
Return value for BaseThread.fileType(), batch file.
void wakeUpClient(Event *e=NULL)
Send a message to the client.
Data & timeConnetcted()
Time at which the client connected.
string appname
Application name.
void prompt(RetValue ret)
Send a prompt to client.
virtual void hk_postexec(CommandParser *cmd, RetValue ret)
Virtual method called after a command has been executed.
#define MCS_CMD_PUT
Command: Upload a file to the work directory.
int argc()
Return number of arguments.
RetValue
Return value for MCS routines.
RetValue type()
Return the event type.
RetValue exec(string cmd, string pars="")
Execution method for user's command.
#define MCS_CMD_CID
Command: Retrieve the Client identifier.
bool givenOpt(string opt)
Check if a certain option has been given.
#define MCS_FT_SCRIPT
Return value for BaseThread.fileType(), script file.
#define MCS_CMD_EXEC
Command: Execute an external program, script, SQL or batch file.
string dbname
Database name, usually the same as Env.appname.
RetValue(* cb_auth)(int &, bool &)
Pointer to a callback function, called by hk_auth().
bool cl_have_db
Activate DB facilities.
vector< string > split(string s, string sep=" ")
Split a string into tokens.
#define MCS_PROMPT_ERROR
Prompt sent after a command raised one error.
RetValue sendQueryRes()
Send query results as it was a file created with the Query.Result2Ascii() method. ...
#define MCS_CMD_TABLELIST
Command: Retrieve the list of tables actually present in the database.
Main include file for all MCS based applications.
bool cl_clean_logout
Clean work dir on user logout.
UserThread(const UserThread &)
Declared to avoid using of default copy constructor.
void addField(Data *d)
Wrapper around Dynamic_Array.push.
bool cmpCmd(string cmd)
Check if the string in the parameter is the same as the command (case insensitive).
#define MCS_STATE_RUNNING
Thread state: the separate thread is executing the run() method.
#define MCS_WARN(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
int code()
Returns the event code.
A general purpose data type.
#define MCS_CMD_DBNAME
Command: Provide the application (database) name.
#define MCS_CMD_USERNAME
Command: Provide user name.
RetValue(* cb_connect)()
Pointer to a callback function, called by hk_connect().
string subst(string s, string what, string with, int op=0)
Perform substitutions on a string.
bool rmDir(string path, enum ThrowExceptions throwexc=THROW)
Removes a directory.
#define MCS_CMD_TABLEINFO
Command: Retrieve information about a table.
#define MCS_FT_BIN
Return value for BaseThread.fileType(), binary file.
#define MCS_OK(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Socket * sock
Socket to client.
#define MCS_PROMPT_OK
Prompt sent after a command has been executed correctly.
Query * query
Query object.
ClientInfo & info()
Return internal ClientInfo structure.
#define MCS_CMD_QUERY
Command: Execute queries on the database.
Data & id()
Client ID, the same as the one returned with the MCS_CMD_CID command.
#define MCS_OPT_SAVEQUERYFITS
Option: Save query result in FITS format.
A class to create separate threads.
#define MCS_PROMPT_WARN
Prompt sent after a command raised one or more warnings.
virtual RetValue hk_auth(int &grants, bool &loginok)
Virtual method called when the user issue the MCS_CMD_DBCONNECT command.
string cmd()
Returns the first token, that is the command.
#define MCS_CMD_NOP
Command: No operation (dummy) command.
int ival() const
Convert internal data to a integer value.
#define MCS_FATAL(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
RetValue(* cb_exec)(CommandParser *, bool &_executed)
Pointer to a callback function, called by hk_exec().
void(* cbwa_auth)()
Pointer to a void callback function without arguments, called by hk_auth().
Data & arg(int i)
Return argument at i-th position.
#define MCS_CMD_CLOSECLIENT
Command: Close the session.
#define MCS_CMD_DBCONNECT
Command: Finalize the authentication process and log in.
#define MCS_OPT_FORCE
Option: Continue execution of commands even if an error occur.
ClientInfo linfo
Structure containing client informations.
virtual void hk_disconnect()
Virtual method called when the user disconnect.
string userName()
Return the user name used to authenticate the client.
void(* cb_disconnect)()
Pointer to a callback function, called by hk_disconnect().
#define MCS_CMD_PASSWORD
Command: Provide password.
void(* cb_postexec)(CommandParser *, RetValue)
Pointer to a callback function, called by hk_postexec().
bool mkDir(string path, mode_t perm=0, enum ThrowExceptions throwexc=THROW)
Create a directory.
bool cl_work
Use private (per user) working dir, otherwise use path.
RetValue Send(Event e, bool log=true)
Send a message to client.
#define MCS_OPT_ALL_ERRORS
Option: Turns all warning into errors, so that a warning can stop the execution.
Namespace for MCS library.
virtual RetValue hk_exec(CommandParser *cmd, bool &cmd_executed)
Virtual method called before executing a command.
void(* cbwa_connect)()
Pointer to a void callback function without arguments, called by hk_connect().