/************************************************************************* * * HTCd - Copyright (C) 1998-2006 Henrik Rydberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include const mstring cron_tag="cron."; const int SSECS=4; TOK_IMPL(def) { expr_t* x=env.arg(2); func_t* tok=Func(*env.toks,env[0],x->expr,tok_t::PUBLIC,env[1]); if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env); } TOK_IMPL(redef) { expr_t* x=env.arg(2); func_t* tok=Func(*env.toks,env[0],x->expr,tok_t::PUBLIC,env[1],1); if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env); } TOK_IMPL(ldef) { if(env.toks->get(env[0])) THROW("htc: local function would override global token"); expr_t* x=env.arg(2); func_t* tok=Func(env.loc,env[0],x->expr,tok_t::PUBLIC,env[1]); if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env); } TOK_IMPL(cron) { mstring name=cron_tag+env[0]; expr_t* x=env.arg(1); cron_t* tok=Cron(*env.toks,name,x->expr,tok_t::PUBLIC,atoi(env[0])); if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env); } /////////////////////////////////////////////////// static void Run(tokmap& m,mstream& out,Env& env,const sref& s) throw(merror_t) { tok_t* p=m.get(s); if(!p) THROW("htc: cannot run "<is_reference()) env.parse(out,((reference_t*)p)->data); else if(!p->is_runnable()) env.parse(out,p->body); } catch(const merror_t& e) { out< cron; int cont=1; for(tokmap* tok=env.toks;tok&&cont;tok=tok->up) { for(Env::iterator p=tok->begin();p!=tok->end();++p) { if((*p)->name.left(cron_tag.size())==cron_tag&&(*p)->is_cron()) { cron.push_back((cron_t*)(*p)); cont=0; } } } while(env.req->is_running()&&cron.size()) { int cont=1; for(int i=0;icron[i]->last+cron[i]->interval) { mstream ms; env.eval(ms,&cron[i]->x,0); cron[i]->last=time(0); cont=0; } } if(cont) sleep(SSECS); } } ////////////////////////////////////////////////////// void envAddFunc(tokmap& T) { TOK_ADD(def,"xxr",tok_t::PUBLIC, "%Define new global function\n" "%Syntax: \\def{varname}{argument string [xr?*]}{body}\n" "%\n" "%The argument string is a sequence of characters describing\n" "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n" "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n" "%The can be only one optional (?) argument.\n" "%The body contains the function body. The arguments are retrieved\n" "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n" "%regardless of where it stands in the sequence.\n" "%\n" "%Generates an error if already defined.\n" ); TOK_ADD(redef,"xxr",tok_t::PRIVATE, "%Redefine global function\n" "%Syntax: \\def{varname}{argument string [xr?*]}{body}\n" "%\n" "%The argument string is a sequence of characters describing\n" "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n" "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n" "%The can be only one optional (?) argument.\n" "%The body contains the function body. The arguments are retrieved\n" "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n" "%regardless of where it stands in the sequence.\n" "%\n" "%Takes precedence over any existing function.\n" ); TOK_ADD(ldef,"xxr",tok_t::PUBLIC, "%Define a local function\n" "%Syntax: \\ldef{varname}{argument string [xr?*]}{body}\n" "%\n" "%The argument string is a sequence of characters describing\n" "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n" "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n" "%The can be only one optional (?) argument.\n" "%The body contains the function body. The arguments are retrieved\n" "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n" "%regardless of where it stands in the sequence.\n" "%\n" "%Local functions work just like global functions, but are only\n" "%accessible from within the current stack frame.\n" ); TOK_ADD(cron,"xr",tok_t::SYSONLY, "%Define a cron function\n" "%Syntax: \\cron{interval}{body}\n" "%\n" "%A cron function is executed every interval seconds,\n" "%when running in cron mode.\n" "%\n" "%See \\run.cron.\n" ); ////////////////////////////////////////////////////// TOK_ADD(run,"x",tok_t::SYSONLY, "%Evaluate the body of variable in current running mode\n" "%Syntax: \\run{varname}\n" "%\n" "%The running modes are:\n" "%\n" "%XINIT Init mode is only used to collect meta information\n" "%XSYSTEM The system mode - everything is accessible\n" "%XPRIVATE Private mode - suitable for in-door custom programs\n" "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n" "% via the web. This is the default mode for all derivative\n" "% functions, as well as for globals and constants.\n" "%\n" "%IT IS A MAJOR SECURITY HAZARD TO EVALUATE UNKNOWN\n" "%VARIABLES IN XSYSTEM MODE!!\n" "%\n" "%If at all, user-supplied information should only be run\n" "%in public mode, for instance to allow the expansion of latex\n" "%commands. NEVER use this mode outside the core.\n" ); TOK_ADD(run_private,"x",tok_t::SYSONLY, "%Evaluate the body of variable in private mode\n" "%Syntax: \\run.private{varname}\n" "%\n" "%The running modes are:\n" "%\n" "%XINIT Init mode is only used to collect meta information\n" "%XSYSONLY The system mode - everything is accessible\n" "%XPRIVATE Private mode - suitable for in-door custom htc code\n" "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n" "% via the web. This is the default mode for all derivative\n" "% functions, as well as for globals and constants.\n" "%\n" "%The execution of sysonly functions is silent, just as it wasn't there.\n" ); TOK_ADD(run_public,"x",tok_t::PRIVATE, "%Evaluate the body of variable in public mode\n" "%Syntax: \\run.public{varname}\n" "%\n" "%The running modes are:\n" "%\n" "%XINIT Init mode is only used to collect meta information\n" "%XSYSONLY The system mode - everything is accessible\n" "%XPRIVATE Private mode - suitable for in-door custom programs\n" "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n" "% via the web. This is the default mode for all derivative\n" "% functions, as well as for globals and constants.\n" "%\n" "%The execution of sysonly or private functions is silent,\n" "%just as they weren't there.\n" ); TOK_ADD(run_local,"x",tok_t::PRIVATE, "%Evaluate the body of the local variable in public mode\n" "%Syntax: \\run.local{varname}\n" "%\n" "%The running modes are:\n" "%\n" "%XINIT Init mode is only used to collect meta information\n" "%XSYSTEM The system mode - everything is accessible\n" "%XPRIVATE Private mode - suitable for in-door custom programs\n" "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n" "% via the web. This is the default mode for all derivative\n" "% functions, as well as for globals and constants.\n" "%\n" "%The execution of sysonly or private functions is silent,\n" "%just as they weren't there.\n" ); TOK_ADD(run_cron,"",tok_t::SYSONLY, "%Go into an infinite loop and run the crontab command.\n" "%Syntax: \\run.cron{}\n" "%\n" "%Note that only cron functions from the highest global level\n" "%where a cron function is defined is run. Hence you may redefine\n" "%earlier crontabs, but cannot mix between levels.\n" "%\n" "%You can only have one crontab of a certain interval.\n" "%\n" "%Produces no output.\n" ); }